Sign in to follow this  
Noobwaker

memcpy to arrays

Recommended Posts

Noobwaker    133
If if have some arrays:
short Array1[101][101][2], x[202];
and I memcpy to Array1:
for(loopf1=0;loopf1<101;loopf1++){
	memcpy(&Array1[loopf1][0][0],x,(202*sizeof(short)));
}
Why would another variable get overwritten? Two other variables that I'm using get overwritten when loopf1==37.

Share this post


Link to post
Share on other sites
lucem    176
You should avoid using memcpy() generally, and rather use dynamic containers like std::list or std::vector, as these are much less error-prone than memcpy'ing things in arrays around yourself.

Share this post


Link to post
Share on other sites
CTar    1134
Quote:
Original post by Noobwaker
I've never used that notation before. Can you do that in C, or just C++? Or am I way off?


What lucem recommended is C++ only (It's a part of the SC++L). On this forum most people automatically assume you use C++.

EDIT: Fixed names

Share this post


Link to post
Share on other sites
snk_kid    1312
Quote:
Original post by CTar
Quote:
Original post by Noobwaker
I've never used that notation before. Can you do that in C, or just C++? Or am I way off?


What Noobwaker recommended is ...


Hmm... was he talking to him/herself [grin].

Share this post


Link to post
Share on other sites
lucem    176
Basically, these are part of the C++ Standard template library.
As most compilers today are C++ compilers, you can use them from C, too, in most cases.
These containers, algortihms and iterators in the STL (and in other libs, too, like Boost:: for example) are really handy, as they base on templates and so a generic containers you can use with every data type.
They handle memory management for you and keep you away from producing segfaults ;), so all you have to do is use them, which simplifies development a lot a times.

Share this post


Link to post
Share on other sites
Conner McCloud    1135
A quick test run with your code doesn't reveal any problems with the memory on either side of Array1 and x, and it looks OK to me [if not a little silly]. What exactly is getting overwritten?

CM

Share this post


Link to post
Share on other sites
yadango    567
it could be possible. if i remember correctly memmove is one function that handles overlapping boundaries. give memmove a try. though one question i have is (since it's been a while since i've used C...) are multidimensional arrays defined to be contiguous (is &Array[i][j] + 2 == &Array[i][j + 1]? i mean if done with new you'd have problems cuz your array size is technically 2, not 202.


short*** Array1 = new (short**)[101];
for(i = 0; i < 101; i++) {
Array1[i] = new (short*)[101];
for(j = 0; j < 101; j++) Array[i][j] = new short[2];
}



[Edited by - yadango on March 12, 2006 11:17:35 AM]

Share this post


Link to post
Share on other sites
Conner McCloud    1135
Quote:
Original post by yadango
it could be possible. if i remember correctly memmove is one function that handles overlapping boundaries. give memmove a try. though one question i have is (since it's been a while since i've used C...) are multidimensional arrays defined to be contiguous (is &Array[i][j] + 2 == &Array[i][j + 1]?

Yes, they are defined to be contiguous, although your example is flawed since pointer arithmetic automatically acounts for type sizes. This assumes the array is statically defined...you can't use malloc for obvious reasons. I'm also not sure whether or not row-major or column-major forms are required. I'm not even sure which is used, since I always have to look up what those words mean. That, by the way, was my first guess. That the wrong ordering was being assumed, so bounds weren't adding up the way he thought they would.

CM

Share this post


Link to post
Share on other sites
Noobwaker    133
The two variables, which are Map.SizeX and Map.SizeY, get overwritten when the loopf1 is 37. If I make x only 201, and memcpy only (201*sizeof(short)), then Array1[loopf1][100][0] gets written to, but Array1[loopf1][100][1] doesn't. So I don't think it's any overflow. Array1 and the Map variables are global, and x is local.

Is there something else I can do that would be just as fast or faster?

(I'm using C incase you don't know)

Share this post


Link to post
Share on other sites
Way Walker    745
Quote:
Original post by Noobwaker
If if have some arrays:
short Array1[101][101][2], x[202];

and I memcpy to Array1:
for(loopf1=0;loopf1<101;loopf1++){
memcpy(&Array1[loopf1][0][0],x,(202*sizeof(short)));
}

Why would another variable get overwritten?

Two other variables that I'm using get overwritten when loopf1==37.


Your code looks correct to me (like it did to others). The suggestion is now that you copy and paste (don't type, you may make typos) an actual code block to exhibits the problem. Preferably, the code block should be a complete program that we can compile.

Here's an example of what such a block could look like (even though it doesn't appear to exhibit your problem):

#include <stdio.h>
#include <string.h>

int main(void) {
short Array1[101][101][2], x[202];
size_t loopf1;

for (loopf1 = 0; loopf1 < 202; loopf1++) {
x[loopf1] = loopf1;
}

for (loopf1 = 0; loopf1 < 101; loopf1++) {
memcpy(Array1[loopf1], x, 202 * sizeof(short));
}

for (loopf1 = 0; loopf1 < 101; loopf1++) {
size_t loopf2;
for (loopf2 = 0; loopf2 < 101; loopf2++) {
printf("%d %d ", (int)Array1[loopf1][loopf2][0], (int)Array1[loopf1][loopf2][1]);
}
printf("\n");
}

return 0;
}





Here's one that uses "sizeof var" instead of "sizeof(type)" and magic numbers to help avoid errors (in particular for the memcpy):

#include <stdio.h>
#include <string.h>

#define MIN(a_, b_) ((a_) < (b_) ? (a_) : (b_))
#define N(a_) (sizeof a_ / sizeof *a_)

int main(void) {
short Array1[101][101][2], x[202];
size_t loopf1;

for (loopf1 = 0; loopf1 < N(x); loopf1++) {
x[loopf1] = loopf1;
}

for (loopf1 = 0; loopf1 < N(Array1); loopf1++) {
memcpy(Array1[loopf1], x, MIN(sizeof Array1[0], sizeof x));
}

for (loopf1 = 0; loopf1 < N(Array1); loopf1++) {
size_t loopf2;
for (loopf2 = 0; loopf2 < N(*Array1); loopf2++) {
printf("%d %d ", (int)Array1[loopf1][loopf2][0], (int)Array1[loopf1][loopf2][1]);
}
printf("\n");
}

return 0;
}


Share this post


Link to post
Share on other sites
Noobwaker    133
Wow, I just found out something really messed up.
	path[37][84][0]=9;
path[37][84][1]=14;

sets Map.SizeX to 9, and Map.SizeY to 14.

What's going on?

Share this post


Link to post
Share on other sites
Way Walker    745
Quote:
Original post by Noobwaker
Wow, I just found out something really messed up.
	path[37][84][0]=9;
path[37][84][1]=14;

sets Map.SizeX to 9, and Map.SizeY to 14.

What's going on?


You have a bug. To be more specific, you either have an overflow or an aliasing problem. Without actual code (*hint* *hint*), it's hard to say exactly what's wrong.

Share this post


Link to post
Share on other sites
xeddiex    238
Quote:
Original post by Noobwaker
Wow, I just found out something really messed up.
	path[37][84][0]=9;
path[37][84][1]=14;

sets Map.SizeX to 9, and Map.SizeY to 14.

What's going on?


To understand what's going on, it's better that you back up a bit and do this with a 2D array. static arrays are contigous. Meaning, if you went out of bounds in a 2D array with the first row, you would land in the second row (assuming you're still within range). This works because of the contigousness, but, it's not recommended that you program this way =)

For example:


char twod[2][10]; // ROW and COLUME

twod[0][10] = 'k';


would set the character value 'k' at indexe's 1 (row) and 0 (colume).



- xeddiex

Share this post


Link to post
Share on other sites
Noobwaker    133
path[37][84][0] should still be in range though since the declaration is
short path[101][101][2];
But my problem is that somehow Map.SizeX is connected with path[37][84][0]. How does something like that happen, and how can I fix it?

Share this post


Link to post
Share on other sites
Way Walker    745
Aliasing is when you have two names for the same data. The most trivial example is:

int a = 1;
int *b = &a;
int *c = &a;

A less trivial example is:

int a[2] = {1, 2};
int *b = a;
int *c = a + 1;

Because here b[1] and *c are the same. Overflow is very similar:

int a[1] = {1};
int b = 2;

Here, a[1] might give you b.

Quote:
Original post by Noobwaker
How does something like that happen, and how can I fix it?


I don't have enough information to answer that question. Take off the tinfoil hat and give us some code to work with.

Share this post


Link to post
Share on other sites
Conner McCloud    1135
Quote:
Original post by Noobwaker
path[37][84][0] should still be in range though since the declaration is
short path[101][101][2];
But my problem is that somehow Map.SizeX is connected with path[37][84][0]. How does something like that happen, and how can I fix it?

We can't tell you what's going on, because, as you noticed, it shouldn't be happening in the first place. This means that something elsewhere must be the problem. Until we see that something elsewhere, you aren't going to get any help.

CM

Share this post


Link to post
Share on other sites
Noobwaker    133
I think it's just my debugger.

It will say that Map.SizeX = -1, but then I put in
loopf1=Map.SizeX;
path[37][84][0]++;
and it says that loopf1 = 30 while still saying that Map.SizeX = -1, then it says that Map.SizeX = 0 once it reaches "path[37][84][0]++;"

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this