Problems with a structure copy - pointers

I am having a compiler issue in Visual Studio 2005 using the standard C compiler when trying to do a structure copy from one location to another.
The types are defined in a file as follows:
definition.h
#define MAX 7
typedef struct{
char recordtext[18];
boolean recordvalid;
}recordtype;
typdef recordtype tabletype[MAX];
typedef struct{
tabletype table;
}global_s;
Let us pretend that a global_s "object" is instantiated and initialized somewhere and a pointer to this structure is created.
#include "definition.h"
global_s global;
global_s* pglobal = &global;
init(&pglobal);
Meanwhile, in another file (and this is where my problem is) i am trying to create a local tabletype object, and fill it with the global table member, using a get method to protect the global (lets pretend it is "static")
#include "definition.h"
extern global_s* pglobal;
tabletype t;
gettable(&t);
void gettabl (tabletype* pt)
{
*pt = pglobal->table;
}
When I go to compile, the line in the gettable function throws a compiler error "error C2106: '=': left operand must be l-value. It looks as though this should behave as a normal copy operation, and in fact if I perform a similar operation on a more basic structure I do not get the error. For example If I copy a structure only containing two integers.
Does anyone have a solid explanation as to why this operation seems to be incorrect?
(Disclaimer: I have developed this code as a scrubbed version of my actual code for example purposes so it may not be 100% correct syntactically, I will edit the question if anyone points out an issue or something needs to be clarified.)

It's the arrays in the struct; they cannot be assigned. You should define an operator=() for each of the structs, and use memcpy on the arrays, or copy them in a loop element by element.

(IF you want to get a reference to your global variable):
I am not sure, if this is correct (and the problem), but I think besides function prototypes, arrays and pointers (to arrays 1. element) are NOT exactly the same thing. And there is a difference between pointer to array and pointer to the 1. element of an array)
Maybe taking the adress of the array:
*pt = &(pglobal->table);
Anyway it might be better not to fetch the address of the whole array but the address of the first element, so that the resulting pointer can be used directly as record array (without dereferencing it)
recordtype* gettable (size_t* puLength)
{
*puLength = MAX;
return &(pglobal->table[0]);
}
(IF you want a copy of the table):
Arrays can't be copied inplace in C90, and of course you have to provide target memory. You would then define a function get table like this:
void gettable (recordtype * const targetArr)
{
size_t i = 0;
for (; i < MAX; i++) targetArr[i] = pglobal->table[i];
return;
}
an fully equivalent function prototype for gettable is:
void gettable(recordtype[] targetArr);
Arrays are provided by refernce as pointer to the first element, when it comes to function parameters. You could again ask for an pointer to the whole array, and dereference it inside gettable. But you always have to copy elementwise.
You can use memcopy to do the job as 1-liner. Modern compilers should generate equally efficent code AFAIK.

Related

Pushing values to a Vector of pointers has garbage values

I am a C++ noob and I have written a method to get text file names including full-paths from a given directory. It gives a garbage value on the vector<wchar_t*> names. I used VS2010 debugger and analysed values. It looks like pointers are going out of scope. On the official C++ reference it says that push_back() copies values and seems like as I am pushing a pointer and it just copies pointers value.
static std::vector<wchar_t*> getFileNames(wchar_t* folder) // ex: c:\\textfiles\\My
{
using namespace std;
vector<wchar_t*> names;
wchar_t search_path[200];
swprintf(search_path, L"%s\\*.txt", folder); // ex: c:\\textfiles\\My\\*.txt
WIN32_FIND_DATA fd;
HANDLE hFind = FindFirstFile((wchar_t*)search_path, &fd);
if(hFind != INVALID_HANDLE_VALUE)
{
do
{
if(! (fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) )
{
std::wstring fullPath(folder);
fullPath += L"\\";
fullPath += std::wstring(fd.cFileName); // cFilename has something like Info.txt
names.push_back((wchar_t*)fullPath.c_str());
}
}while(FindNextFile(hFind, &fd)); //goes out of scope and values become garbage
FindClose(hFind);
}
return names; //vector with garbage values
}
Is it possible to get wchar_t* pushed in to the vector someway, a better work around rather than dynamically allocating memory or using heap variables?
Can I get compiler warning for mistakes like this on VS2010 or any VS version(Now I only get casting warning and errors)?
swprintf might overflow the buffer.
(wchar_t*)search_path is a superfluous cast.
Never break out the big guns if you don't need them.
if(! (fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) ) means you only ignore directories without interesting attributes.
fullPath += std::wstring(fd.cFileName); another superfluous cast.
names.push_back((wchar_t*)fullPath.c_str()); pushes a pointer to the internal buffer of fullpath into names, even though it will be destroyed at the end of the block.
What you should do is change the signature to
static std::vector<std::wstring> getFileNames(std::wstring folder)
Or at least
static std::vector<std::unique_ptr<wchar_t>> getFileNames(wchar_t* folder)
to take advantage of RAII and reduce the chance for errors.
In any case, you should rewrite the function, and should take advantage of the standard-library internally.
As an example, with the proper prototype:
static std::vector<std::wstring> getFileNames(std::wstring folder) {
std::vector<std::wstring> names;
WIN32_FIND_DATA fd;
HANDLE hFind = FindFirstFile((folder+L"\\*.txt").c_str(), &fd);
if(hFind == INVALID_HANDLE_VALUE)
return names;
auto lam = [](HANDLE* p){FindClose(*p);}
std::unique_ptr<HANDLE, decltype(lam)> guard(&hFind, lam);
folder += L"\\";
do {
if(! (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
names.push_back(folder+fd.cFileName);
} while(FindNextFile(hFind, &fd));
return names;
}
Ideally, you should store class objects in your vector, instead of character pointers (or wchar_t pointers). You can do it, but it requires some extra work. That's the part that you're missing.
The issue you're seeing is exactly what you describe: the character arrays that are owned by the wstring objects are being destroyed when the wstring goes out of scope. By using wstring::c_str(), you are not creating an independent copy of the character array, you're just looking at the one that it already has created for its own use.
So you need a way to keep a character array around longer. Either you could use the wstring, or you need to copy the character array into one of your own.
The minimal change would be something like this:
std::wstring fullPath(folder);
fullPath += L"\\";
fullPath += std::wstring(fd.cFileName); // cFilename has something like Info.txt
wchar_t *wsz = new wchar_t[fullPath.size() + 1];
wcsncpy(wsz, fullPath.c_str(), fullPath.size());
names.push_back(wsz);
That's enough to get your strings into the vector, but because you're using character pointers, it's also your responsibility to clean them up. So when you are done using the vector, you will need to iterate through and delete each one of them before you let the vector be destroyed.
As I mention in a comment below, it's much simpler to use a std::vector. There are libraries that can help you with the memory management parts, if you must use wchar_t*. You caould take a look at the Boost Smart Pointer library, for example.
The variable fullPath is a local variable.
It goes out of scope.
That is the reason the pointers are becoming junk.
Allocate a dynamic memory as
vector<wstring*> names;// instead of vector<wchar_t*> names;
std::wstring *fullPath = new wstring(folder);
Never store references of objects into a list if you are not aware of their scope.

QMap Memory Error

I am doing one project in which I define a data types like below
typedef QVector<double> QFilterDataMap1D;
typedef QMap<double, QFilterDataMap1D> QFilterDataMap2D;
Then there is one class with the name of mono_data in which i have define this variable
QFilterMap2D valid_filters;
mono_data Scan_data // Class
Now i am reading one variable from a .mat file and trying to save it in to above "valid_filters" QMap.
Qt Code: Switch view
for(int i=0;i<1;i++)
{
for(int j=0;j<1;j++)
{
Scan_Data.valid_filters[i][j]=valid_filters[i][j];
printf("\nValid_filters=%f",Scan_Data.valid_filters[i][j]);
}
}
The transferring is done successfully but then it gives run-time error
Windows has triggered a breakpoint in SpectralDataCollector.exe.
This may be due to a corruption of the heap, and indicates a bug in
SpectralDataCollector.exe or any of the DLLs it has loaded.
The output window may have more diagnostic information
Can anyone help in solving this problem. It will be of great help to me.
Thanks
Different issues here:
1. Using double as key type for a QMap
Using a QMap<double, Foo> is a very bad idea. the reason is that this is a container that let you access a Foo given a double. For instance:
map[0.45] = foo1;
map[15.74] = foo2;
This is problematic, because then, to retrieve the data contained in map[key], you have to test if key is either equal, smaller or greater than other keys in the maps. In your case, the key is a double, and testing if two doubles are equals is not a "safe" operation.
2. Using an int as key while you defined it was double
Here:
Scan_Data.valid_filters[i][j]=valid_filters[i][j];
i is an integer, and you said it should be a double.
3. Your loop only test for (i,j) = (0,0)
Are you aware that
for(int i=0;i<1;i++)
{
for(int j=0;j<1;j++)
{
Scan_Data.valid_filters[i][j]=valid_filters[i][j];
printf("\nValid_filters=%f",Scan_Data.valid_filters[i][j]);
}
}
is equivalent to:
Scan_Data.valid_filters[0][0]=valid_filters[0][0];
printf("\nValid_filters=%f",Scan_Data.valid_filters[0][0]);
?
4. Accessing a vector with operator[] is not safe
When you do:
Scan_Data.valid_filters[i][j]
You in fact do:
QFilterDataMap1D & v = Scan_Data.valid_filters[i]; // call QMap::operator[](double)
double d = v[j]; // call QVector::operator[](int)
The first one is safe, and create the entry if it doesn't exist. The second one is not safe, the jth element in you vector must already exist otherwise it would crash.
Solution
It seems you in fact want a 2D array of double (i.e., a matrix). To do this, use:
typedef QVector<double> QFilterDataMap1D;
typedef QVector<QFilterDataMap1D> QFilterDataMap2D;
Then, when you want to transfer one in another, simply use:
Scan_Data.valid_filters = valid_filters;
Or if you want to do it yourself:
Scan_Data.valid_filters.clear();
for(int i=0;i<n;i++)
{
Scan_Data.valid_filters << QFilterDataMap1D();
for(int j=0;j<m;j++)
{
Scan_Data.valid_filters[i] << valid_filters[i][j];
printf("\nValid_filters=%f",Scan_Data.valid_filters[i][j]);
}
}
If you want a 3D matrix, you would use:
typedef QVector<QFilterDataMap2D> QFilterDataMap3D;

Sometimes fails to create heap object (Eigen with custom structure)

I'm using a project which uses the Eigen library. I've had to already fixed an issue where when using the data types provided by eigen within a STL, I get an align error
error C2719: '_Val': formal parameter with __declspec(align('16'))
won't be aligned
see
http://eigen.tuxfamily.org/dox/TopicStlContainers.html or -http://www.mrpt.org/Matrices_vectors_arrays_and_Linear_Algebra_MRPT_and_Eigen_classes)
Once this was fixed i could compile and run.
But now at run time I'm getting another error
Debug Error!
R6010
abort() has been called.
So the code in question references my structure and a vector of my structure (with the eigen specially aligned fix):
typedef struct {
Vector4f v4;
Matrix4f M4;
bool b;
} my_struct;
typedef std::vector<my_struct, Eigen::aligned_allocator<my_struct>> my_struct;
Then my code fails after a when I try to create a new my_struct after a certain number of iterations (it can sometimes creates the new object, with no problems), other times it fails.
for (int i = 0; i<len; i++) {
Vector4f vec;
Matrix4f mat;
my_struct* temp = new my_struct();
}
Any ideas?
Tom
Without -DNDEBUG, you should have got an assert sending you to this page. In your case, you should follow this one. In short, add EIGEN_MAKE_ALIGNED_OPERATOR_NEW to your structure such that new my_struct call an aligned memory allocator.

go tour when to not use pointer to struct literal in a variable

Per the Go tour page 28 and page 53
They show a variable that is a pointer to a struct literal. Why is this not the default behavior? I'm unfamiliar with C, so it's hard to wrap my head around it. The only time I can see when it might not be more beneficial to use a pointer is when the struct literal is unique, and won't be in use for the rest program and so you would want it to be garbage collected as soon as possible. I'm not even sure if a modern language like Go even works that way.
My question is this. When should I assign a pointer to a struct literal to a variable, and when should I assign the struct literal itself?
Thanks.
Using a pointer instead of just a struct literal is helpful when
the struct is big and you pass it around
you want to share it, that is that all modifications affect your struct instead of affecting a copy
In other cases, it's fine to simply use the struct literal. For a small struct, you can think about the question just as using an int or an *int : most of the times the int is fine but sometimes you pass a pointer so that the receiver can modify your int variable.
In the Go tour exercises you link to, the Vertex struct is small and has about the same semantic than any number. In my opinion it would have been fine to use it as struct directly and to define the Scaled function in #53 like this :
func (v Vertex) Scaled(f float64) Vertex {
v.X = v.X * f
v.Y = v.Y * f
return v
}
because having
v2 := v1.Scaled(5)
would create a new vertex just like
var f2 float32 = f1 * 5
creates a new float.
This is similar to how is handled the standard Time struct (defined here), which is usually kept in variables of type Time and not *Time.
But there is no definite rule and, depending on the use, I could very well have kept both Scale and Scaled.
You're probably right that most of the time you want pointers, but personally I find the need for an explicit pointer refreshing. It makes it so there's no difference between int and MyStruct. They behave the same way.
If you compare this to C# - a language which implements what you are suggesting - I find it confusing that the semantics of this:
static void SomeFunction(Point p)
{
p.x = 1;
}
static void Main()
{
Point p = new Point();
SomeFunction(p);
// what is p.x?
}
Depend on whether or not Point is defined as a class or a struct.

Initialising an associative array of struct values and string keys

(for the "D" programming language)
I've been struggling trying to initialise an associative array that has struct elements and should be index-able by a string. I would import it as a module from a separate file.
This is what I want to achieve (and it doesn't work --- I don't know if this is even possible):
mnemonic_info[string] mnemonic_table = [
/* name, format, opcode */
"ADD": {mnemonic_format.Format3M, 0x18},
...
/* NOTE: mnemonic_format is an enum type. */
/* mnemonic_info is a struct with a mnemonic_format and an ubyte */
];
Note that this works fine for arrays indexable by integers.
Optimally, I would like this to be evaluated at compile-time, as I won't be changing it. However, if it's not possible, I would be glad if you told me of the best way to build such an array at/before immediate run-time.
I need this because I'm writing an assembler.
I have searched SO and the internets for an answer, but could only find examples with integers, and other things I didn't understand or couldn't make to work.
I really like D so far but it seems hard to learn due to there not being many tutorials online.
Thanks!
On a side note: is it possible to use Tuples for associative array elements instead of a custom struct?
Edit
There is one way I found so far, but it's pretty ugly:
mnemonic_info[string] mnemonic_table;
static this() { // Not idea what this does.
mnemonic_info entry;
entry.format = mnemonic_format.Format3M;
entry.opcode = 0x18;
mnemonic_table["ADD"] = entry;
/* ... for all entries. */
}
In D, built-in associative array literals are always created in runtime, so initializing a global associative array by assigning it some value at declaration place is currently impossible.
As you found yourself, you can workaround that by assigning a value to associative array in module constructor.
The other problem in your code is struct initialization literals. You should prefer D-style struct initializers to C-style ones.
Example:
struct Foo {
int a;
string b;
}
Foo[string] global;
static this() {
global = [
"foo" : Foo(1, "hurr"),
"bar" : Foo(2, "durr")
];
}
void main() {
assert(global["foo"].a == 1);
}

Resources