Allocation of a multidimensional array of structures

M

Michel Rouzic

Hi,

I've recently met issues with my program which can only be explained
by heap corruption, so I've tried debugging my program with Valgrind,
and here's what I get with the following multidimensional array
allocation code :

typedef struct
{
int32_t speed;
int16_t height;
} lut_entry;

lut_entry ***lut; // <-global pointer

void lut_alloc()
{
...
lut = malloc(LUT_HC * sizeof(lut_entry **));
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
for (id=0; id<LUT_DC; id++)
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry)); // <- line 1407
}
...
}

int main()
{
...
lut_alloc(); // <- line 1580
...
}

*********Valgrind output*********

==6051== Address 0x4FE8D5C is 4 bytes after a block of size 1,152
alloc'd
==6051== at 0x401F95F: calloc (vg_replace_malloc.c:279)
==6051== by 0x804C587: lut_alloc (main.c:1407)
==6051== by 0x804CECB: main (main.c:1580)

I've been allocating multidimensional arrays this way for years
(although not with structs until now), and I've never had such issues
(although I never used Valgrind before to verify that). Would anyone
know what's wrong with my code?

Thanks in advance.
 
M

Malcolm McLean

Michel Rouzic said:
Hi,

I've recently met issues with my program which can only be explained
by heap corruption, so I've tried debugging my program with Valgrind,
and here's what I get with the following multidimensional array
allocation code :

typedef struct
{
int32_t speed;
int16_t height;
} lut_entry;

lut_entry ***lut; // <-global pointer

void lut_alloc()
{
...
lut = malloc(LUT_HC * sizeof(lut_entry **));
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
for (id=0; id<LUT_DC; id++)
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry)); // <- line 1407
}
...
}

int main()
{
...
lut_alloc(); // <- line 1580
...
}

*********Valgrind output*********

==6051== Address 0x4FE8D5C is 4 bytes after a block of size 1,152
alloc'd
==6051== at 0x401F95F: calloc (vg_replace_malloc.c:279)
==6051== by 0x804C587: lut_alloc (main.c:1407)
==6051== by 0x804CECB: main (main.c:1580)

I've been allocating multidimensional arrays this way for years
(although not with structs until now), and I've never had such issues
(although I never used Valgrind before to verify that). Would anyone
know what's wrong with my code?

Thanks in advance.
You have failed to check your malloc()s. 3D arrays get very big even for
small dimensions.
 
M

Michel Rouzic

I've recently met issues with my program which can only be explained
by heap corruption, so I've tried debugging my program with Valgrind,
and here's what I get with the following multidimensional array
allocation code :
typedef struct
{
int32_t speed;
int16_t height;
} lut_entry;
lut_entry ***lut; // <-global pointer
void lut_alloc()
{
...
lut = malloc(LUT_HC * sizeof(lut_entry **));
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
for (id=0; id<LUT_DC; id++)
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry)); // <- line 1407
}
...
}
int main()
{
...
lut_alloc(); // <- line 1580
...
}
*********Valgrind output*********
==6051== Address 0x4FE8D5C is 4 bytes after a block of size 1,152
alloc'd
==6051== at 0x401F95F: calloc (vg_replace_malloc.c:279)
==6051== by 0x804C587: lut_alloc (main.c:1407)
==6051== by 0x804CECB: main (main.c:1580)
I've been allocating multidimensional arrays this way for years
(although not with structs until now), and I've never had such issues
(although I never used Valgrind before to verify that). Would anyone
know what's wrong with my code?
Thanks in advance.

You have failed to check your malloc()s. 3D arrays get very big even for
small dimensions.

Later I checked by checking all my allocations for NULL returns with
fprintf's, and I had no NULLs. If I had NULLs, wouldn't my app sigsegv
anyways? Anyways, my array is "only" about 1.7 MB.
 
R

Richard Heathfield

Malcolm McLean said:

You have failed to check your malloc()s. 3D arrays get very big even
for small dimensions.

Yes, malloc can fail, even on systems with a great deal of RAM
available, when your program tries to allocate a great deal of RAM + 1.
It's worth bearing in mind, Malcolm.
 
C

CBFalconer

Michel said:
I've recently met issues with my program which can only be
explained by heap corruption, so I've tried debugging my program
with Valgrind, and here's what I get with the following
multidimensional array allocation code :

typedef struct
{
int32_t speed;
int16_t height;
} lut_entry;

lut_entry ***lut; // <-global pointer

void lut_alloc()
{

Apart from the other comments, why are you using K&R C rather than
properly prototyped C functions? After fixing that, consider
passing parameters rather than using globals.
 
B

Barry Schwarz

I've recently met issues with my program which can only be explained
by heap corruption, so I've tried debugging my program with Valgrind,
and here's what I get with the following multidimensional array
allocation code :
typedef struct
{
int32_t speed;
int16_t height;
} lut_entry;
lut_entry ***lut; // <-global pointer
void lut_alloc()
{
...
lut = malloc(LUT_HC * sizeof(lut_entry **));
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
for (id=0; id<LUT_DC; id++)
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry)); // <- line 1407
}
...
}
int main()
{
...
lut_alloc(); // <- line 1580
...
}
*********Valgrind output*********
==6051== Address 0x4FE8D5C is 4 bytes after a block of size 1,152
alloc'd
==6051== at 0x401F95F: calloc (vg_replace_malloc.c:279)
==6051== by 0x804C587: lut_alloc (main.c:1407)
==6051== by 0x804CECB: main (main.c:1580)
I've been allocating multidimensional arrays this way for years
(although not with structs until now), and I've never had such issues
(although I never used Valgrind before to verify that). Would anyone
know what's wrong with my code?
Thanks in advance.

You have failed to check your malloc()s. 3D arrays get very big even for
small dimensions.

Later I checked by checking all my allocations for NULL returns with
fprintf's, and I had no NULLs. If I had NULLs, wouldn't my app sigsegv
anyways? Anyways, my array is "only" about 1.7 MB.

If any of your allocations had failed, your code would invoke
undefined behavior. There is no guarantee that the behavior would
manifest itself as a segfault. In fact, a segfault would be one of
the "better" manifestations. Unfortunately, one of the worse
manifestations is "appear to work until it is almost impossible to
find what the real problem is."

How does fprintf let you know if any of the allocations failed?

Is there any other code in the for loops you are not showing us?


Remove del for email
 
M

Michel Rouzic

CBFalconer said:
Apart from the other comments, why are you using K&R C rather than
properly prototyped C functions?

In case you're refering to writing void lut_alloc(); and then void
lut_alloc(){...} I have yet to find out how it is better to do things
this way. But since there was a why in your question I guess it's
because it's simpler, it avoids a redundancy that I deem useless
(maybe out of ignorance?) and it avoid making mistakes by changing a
line and not changing the other one accordingly.

Or to turn the question around, why should I use that prototyping
thing?
After fixing that, consider
passing parameters rather than using globals.

Well, while I'm aware that it's better to avoid using globals, it's
really more convenient to make the LUT global here, considered it's
more convenient to write code this way and that it'd make one more
argument to pass from function to function, so I don't see why I
shouldn't use a global pointer here.
 
M

Michel Rouzic

Barry said:
Hi,

I've recently met issues with my program which can only be explained
by heap corruption, so I've tried debugging my program with Valgrind,
and here's what I get with the following multidimensional array
allocation code :

typedef struct
{
int32_t speed;
int16_t height;
} lut_entry;

lut_entry ***lut; // <-global pointer

void lut_alloc()
{
...
lut = malloc(LUT_HC * sizeof(lut_entry **));
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
for (id=0; id<LUT_DC; id++)
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry)); // <- line 1407
}
...
}

int main()
{
...
lut_alloc(); // <- line 1580
...
}

*********Valgrind output*********

==6051== Address 0x4FE8D5C is 4 bytes after a block of size 1,152
alloc'd
==6051== at 0x401F95F: calloc (vg_replace_malloc.c:279)
==6051== by 0x804C587: lut_alloc (main.c:1407)
==6051== by 0x804CECB: main (main.c:1580)

I've been allocating multidimensional arrays this way for years
(although not with structs until now), and I've never had such issues
(although I never used Valgrind before to verify that). Would anyone
know what's wrong with my code?

Thanks in advance.

You have failed to check your malloc()s. 3D arrays get very big even for
small dimensions.

Later I checked by checking all my allocations for NULL returns with
fprintf's, and I had no NULLs. If I had NULLs, wouldn't my app sigsegv
anyways? Anyways, my array is "only" about 1.7 MB.

If any of your allocations had failed, your code would invoke
undefined behavior. There is no guarantee that the behavior would
manifest itself as a segfault. In fact, a segfault would be one of
the "better" manifestations. Unfortunately, one of the worse
manifestations is "appear to work until it is almost impossible to
find what the real problem is."

Well it sounds a hell of a lot like my problem, I must say.
How does fprintf let you know if any of the allocations failed?

lut = malloc(LUT_HC * sizeof(lut_entry **));
if (lut == NULL)
fprintf(stderr, "malloc returned null on lut\n");
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
if (lut[ih] == NULL)
fprintf(stderr, "malloc returned null on lut[%d]\n", ih);
for (id=0; id<LUT_DC; id++)
{
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry));
if (lut[ih][id] == NULL)
fprintf(stderr, "malloc returned null on lut[%d][%d]\n", ih, id);
}
}
Is there any other code in the for loops you are not showing us?

Nope, and then if I didn't show the code with the fprintf's in the
loops it's simply because I hadn't done it yet at the time of the
original posting. By the way, am I even checking my malloc returns
properly?
 
B

Barry Schwarz

Barry said:
Hi,

I've recently met issues with my program which can only be explained
by heap corruption, so I've tried debugging my program with Valgrind,
and here's what I get with the following multidimensional array
allocation code :

typedef struct
{
int32_t speed;
int16_t height;
} lut_entry;

lut_entry ***lut; // <-global pointer

void lut_alloc()
{
...
lut = malloc(LUT_HC * sizeof(lut_entry **));
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
for (id=0; id<LUT_DC; id++)
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry)); // <- line 1407
}
...
}

int main()
{
...
lut_alloc(); // <- line 1580
...
}

*********Valgrind output*********

==6051== Address 0x4FE8D5C is 4 bytes after a block of size 1,152
alloc'd
==6051== at 0x401F95F: calloc (vg_replace_malloc.c:279)
==6051== by 0x804C587: lut_alloc (main.c:1407)
==6051== by 0x804CECB: main (main.c:1580)

I've been allocating multidimensional arrays this way for years
(although not with structs until now), and I've never had such issues
(although I never used Valgrind before to verify that). Would anyone
know what's wrong with my code?

Thanks in advance.

You have failed to check your malloc()s. 3D arrays get very big even for
small dimensions.

Later I checked by checking all my allocations for NULL returns with
fprintf's, and I had no NULLs. If I had NULLs, wouldn't my app sigsegv
anyways? Anyways, my array is "only" about 1.7 MB.

If any of your allocations had failed, your code would invoke
undefined behavior. There is no guarantee that the behavior would
manifest itself as a segfault. In fact, a segfault would be one of
the "better" manifestations. Unfortunately, one of the worse
manifestations is "appear to work until it is almost impossible to
find what the real problem is."

Well it sounds a hell of a lot like my problem, I must say.
How does fprintf let you know if any of the allocations failed?

lut = malloc(LUT_HC * sizeof(lut_entry **));
if (lut == NULL)
fprintf(stderr, "malloc returned null on lut\n");
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
if (lut[ih] == NULL)
fprintf(stderr, "malloc returned null on lut[%d]\n", ih);
for (id=0; id<LUT_DC; id++)
{
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry));
if (lut[ih][id] == NULL)
fprintf(stderr, "malloc returned null on lut[%d][%d]\n", ih, id);
}
}
Is there any other code in the for loops you are not showing us?

Nope, and then if I didn't show the code with the fprintf's in the
loops it's simply because I hadn't done it yet at the time of the
original posting. By the way, am I even checking my malloc returns
properly?

The check is correct but the code that executes if malloc fails is
incomplete. For example, once you know that lut is NULL, you cannot
attempt any of the subsequent allocations. At this point, you must
(gracefully) exit the function or terminate the program. The same is
true for the other two checks.


Remove del for email
 
B

Barry Schwarz

In case you're refering to writing void lut_alloc(); and then void
lut_alloc(){...} I have yet to find out how it is better to do things
this way. But since there was a why in your question I guess it's
because it's simpler, it avoids a redundancy that I deem useless
(maybe out of ignorance?) and it avoid making mistakes by changing a
line and not changing the other one accordingly.

Or to turn the question around, why should I use that prototyping
thing?

If the call to lut_alloc is before the definition of the function, you
should have a prototype in scope to allow the compiler to check that
you are calling it correctly. In C99 it is mandatory; in C89 it is
just good practice and helps avoid undefined behavior.
Well, while I'm aware that it's better to avoid using globals, it's
really more convenient to make the LUT global here, considered it's
more convenient to write code this way and that it'd make one more
argument to pass from function to function, so I don't see why I
shouldn't use a global pointer here.

Convenience is good. Unfortunately that convenience comes at a price
which frequently makes it non-cost-effective. Global variables make
debugging much harder. Given the omissions in the code you have shown
us, this may (admittedly unlikely) be part of the problem you are
having.


Remove del for email
 
M

Malcolm McLean

Michel Rouzic said:
Barry said:
Hi,

I've recently met issues with my program which can only be explained
by heap corruption, so I've tried debugging my program with
Valgrind,
and here's what I get with the following multidimensional array
allocation code :

typedef struct
{
int32_t speed;
int16_t height;
} lut_entry;

lut_entry ***lut; // <-global pointer

void lut_alloc()
{
...
lut = malloc(LUT_HC * sizeof(lut_entry **));
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
for (id=0; id<LUT_DC; id++)
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry)); // <- line 1407
}
...
}

int main()
{
...
lut_alloc(); // <- line 1580
...
}

*********Valgrind output*********

==6051== Address 0x4FE8D5C is 4 bytes after a block of size 1,152
alloc'd
==6051== at 0x401F95F: calloc (vg_replace_malloc.c:279)
==6051== by 0x804C587: lut_alloc (main.c:1407)
==6051== by 0x804CECB: main (main.c:1580)

I've been allocating multidimensional arrays this way for years
(although not with structs until now), and I've never had such
issues
(although I never used Valgrind before to verify that). Would anyone
know what's wrong with my code?

Thanks in advance.

You have failed to check your malloc()s. 3D arrays get very big even
for
small dimensions.

Later I checked by checking all my allocations for NULL returns with
fprintf's, and I had no NULLs. If I had NULLs, wouldn't my app sigsegv
anyways? Anyways, my array is "only" about 1.7 MB.

If any of your allocations had failed, your code would invoke
undefined behavior. There is no guarantee that the behavior would
manifest itself as a segfault. In fact, a segfault would be one of
the "better" manifestations. Unfortunately, one of the worse
manifestations is "appear to work until it is almost impossible to
find what the real problem is."

Well it sounds a hell of a lot like my problem, I must say.
How does fprintf let you know if any of the allocations failed?

lut = malloc(LUT_HC * sizeof(lut_entry **));
if (lut == NULL)
fprintf(stderr, "malloc returned null on lut\n");
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
if (lut[ih] == NULL)
fprintf(stderr, "malloc returned null on lut[%d]\n", ih);
for (id=0; id<LUT_DC; id++)
{
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry));
if (lut[ih][id] == NULL)
fprintf(stderr, "malloc returned null on lut[%d][%d]\n", ih, id);
}
}
Is there any other code in the for loops you are not showing us?

Nope, and then if I didn't show the code with the fprintf's in the
loops it's simply because I hadn't done it yet at the time of the
original posting. By the way, am I even checking my malloc returns
properly?
If the total structure is only 1.7MB then the problem is unlikely to be a
malloc() fail.
The code seems to be correct - apart from the technical problem of not
calling exit() - but that is vanishingly unlikely to be the root error.

I suspect that in later code you are traversing the indices in the wrong
order. If you compile with a boundschecker it might pick it up.
(Make sure you have #included stdlib.h, that could also mess things up ).
 
H

Harald van =?UTF-8?B?RMSzaw==?=

Barry said:
If the call to lut_alloc is before the definition of the function, you
should have a prototype in scope to allow the compiler to check that
you are calling it correctly. In C99 it is mandatory; in C89 it is
just good practice and helps avoid undefined behavior.

C99 does not require function prototypes. C99 does require explicit function
declarations, but they may be either prototyped or unprototyped.

Invalid C99:

int main() {
return f();
}
int f() {
return 0;
}

Valid C99:

int f();
int main() {
return 1 ? f() : f(0);
}
int f() {
return 0;
}
 
M

Michel Rouzic

Malcolm said:
Michel Rouzic said:
Barry said:
On Sat, 23 Jun 2007 11:33:35 -0700, Michel Rouzic



Hi,

I've recently met issues with my program which can only be explained
by heap corruption, so I've tried debugging my program with
Valgrind,
and here's what I get with the following multidimensional array
allocation code :

typedef struct
{
int32_t speed;
int16_t height;
} lut_entry;

lut_entry ***lut; // <-global pointer

void lut_alloc()
{
...
lut = malloc(LUT_HC * sizeof(lut_entry **));
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
for (id=0; id<LUT_DC; id++)
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry)); // <- line 1407
}
...
}

int main()
{
...
lut_alloc(); // <- line 1580
...
}

*********Valgrind output*********

==6051== Address 0x4FE8D5C is 4 bytes after a block of size 1,152
alloc'd
==6051== at 0x401F95F: calloc (vg_replace_malloc.c:279)
==6051== by 0x804C587: lut_alloc (main.c:1407)
==6051== by 0x804CECB: main (main.c:1580)

I've been allocating multidimensional arrays this way for years
(although not with structs until now), and I've never had such
issues
(although I never used Valgrind before to verify that). Would anyone
know what's wrong with my code?

Thanks in advance.

You have failed to check your malloc()s. 3D arrays get very big even
for
small dimensions.

Later I checked by checking all my allocations for NULL returns with
fprintf's, and I had no NULLs. If I had NULLs, wouldn't my app sigsegv
anyways? Anyways, my array is "only" about 1.7 MB.

If any of your allocations had failed, your code would invoke
undefined behavior. There is no guarantee that the behavior would
manifest itself as a segfault. In fact, a segfault would be one of
the "better" manifestations. Unfortunately, one of the worse
manifestations is "appear to work until it is almost impossible to
find what the real problem is."

Well it sounds a hell of a lot like my problem, I must say.
How does fprintf let you know if any of the allocations failed?

lut = malloc(LUT_HC * sizeof(lut_entry **));
if (lut == NULL)
fprintf(stderr, "malloc returned null on lut\n");
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
if (lut[ih] == NULL)
fprintf(stderr, "malloc returned null on lut[%d]\n", ih);
for (id=0; id<LUT_DC; id++)
{
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry));
if (lut[ih][id] == NULL)
fprintf(stderr, "malloc returned null on lut[%d][%d]\n", ih, id);
}
}
Is there any other code in the for loops you are not showing us?

Nope, and then if I didn't show the code with the fprintf's in the
loops it's simply because I hadn't done it yet at the time of the
original posting. By the way, am I even checking my malloc returns
properly?
If the total structure is only 1.7MB then the problem is unlikely to be a
malloc() fail.
The code seems to be correct - apart from the technical problem of not
calling exit() - but that is vanishingly unlikely to be the root error.

I suspect that in later code you are traversing the indices in the wrong
order.

If by that you mean doing lut[ia][ih][id] instead of lut[ih][id][ia]
then no, I checked every instance of my use of this array and
everything is in the correct order.
If you compile with a boundschecker it might pick it up.

How do I do that? I found a bounds checker option for gcc but it's
said it only works for fortran and java.
 
M

Malcolm McLean

Michel Rouzic said:
Malcolm said:
Michel Rouzic said:
Barry Schwarz wrote:
On Sat, 23 Jun 2007 11:33:35 -0700, Michel Rouzic

On Jun 23, 8:02 pm, "Malcolm McLean" <[email protected]>
wrote:


Hi,

I've recently met issues with my program which can only be
explained
by heap corruption, so I've tried debugging my program with
Valgrind,
and here's what I get with the following multidimensional array
allocation code :

typedef struct
{
int32_t speed;
int16_t height;
} lut_entry;

lut_entry ***lut; // <-global pointer

void lut_alloc()
{
...
lut = malloc(LUT_HC * sizeof(lut_entry **));
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
for (id=0; id<LUT_DC; id++)
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry)); // <- line 1407
}
...
}

int main()
{
...
lut_alloc(); // <- line 1580
...
}

*********Valgrind output*********

==6051== Address 0x4FE8D5C is 4 bytes after a block of size
1,152
alloc'd
==6051== at 0x401F95F: calloc (vg_replace_malloc.c:279)
==6051== by 0x804C587: lut_alloc (main.c:1407)
==6051== by 0x804CECB: main (main.c:1580)

I've been allocating multidimensional arrays this way for years
(although not with structs until now), and I've never had such
issues
(although I never used Valgrind before to verify that). Would
anyone
know what's wrong with my code?

Thanks in advance.

You have failed to check your malloc()s. 3D arrays get very big
even
for
small dimensions.

Later I checked by checking all my allocations for NULL returns with
fprintf's, and I had no NULLs. If I had NULLs, wouldn't my app
sigsegv
anyways? Anyways, my array is "only" about 1.7 MB.

If any of your allocations had failed, your code would invoke
undefined behavior. There is no guarantee that the behavior would
manifest itself as a segfault. In fact, a segfault would be one of
the "better" manifestations. Unfortunately, one of the worse
manifestations is "appear to work until it is almost impossible to
find what the real problem is."

Well it sounds a hell of a lot like my problem, I must say.

How does fprintf let you know if any of the allocations failed?

lut = malloc(LUT_HC * sizeof(lut_entry **));
if (lut == NULL)
fprintf(stderr, "malloc returned null on lut\n");
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
if (lut[ih] == NULL)
fprintf(stderr, "malloc returned null on lut[%d]\n", ih);
for (id=0; id<LUT_DC; id++)
{
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry));
if (lut[ih][id] == NULL)
fprintf(stderr, "malloc returned null on lut[%d][%d]\n", ih, id);
}
}

Is there any other code in the for loops you are not showing us?

Nope, and then if I didn't show the code with the fprintf's in the
loops it's simply because I hadn't done it yet at the time of the
original posting. By the way, am I even checking my malloc returns
properly?
If the total structure is only 1.7MB then the problem is unlikely to be a
malloc() fail.
The code seems to be correct - apart from the technical problem of not
calling exit() - but that is vanishingly unlikely to be the root error.

I suspect that in later code you are traversing the indices in the wrong
order.

If by that you mean doing lut[ia][ih][id] instead of lut[ih][id][ia]
then no, I checked every instance of my use of this array and
everything is in the correct order.
If you compile with a boundschecker it might pick it up.

How do I do that? I found a bounds checker option for gcc but it's
said it only works for fortran and java.
Try it anyway. It can't do any harm, as long as you remember that a negative
result doesn't necessarily mean no corruption.
 
M

Michel Rouzic

Malcolm said:
Michel Rouzic said:
Malcolm said:
Barry Schwarz wrote:
On Sat, 23 Jun 2007 11:33:35 -0700, Michel Rouzic

On Jun 23, 8:02 pm, "Malcolm McLean" <[email protected]>
wrote:


Hi,

I've recently met issues with my program which can only be
explained
by heap corruption, so I've tried debugging my program with
Valgrind,
and here's what I get with the following multidimensional array
allocation code :

typedef struct
{
int32_t speed;
int16_t height;
} lut_entry;

lut_entry ***lut; // <-global pointer

void lut_alloc()
{
...
lut = malloc(LUT_HC * sizeof(lut_entry **));
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
for (id=0; id<LUT_DC; id++)
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry)); // <- line 1407
}
...
}

int main()
{
...
lut_alloc(); // <- line 1580
...
}

*********Valgrind output*********

==6051== Address 0x4FE8D5C is 4 bytes after a block of size
1,152
alloc'd
==6051== at 0x401F95F: calloc (vg_replace_malloc.c:279)
==6051== by 0x804C587: lut_alloc (main.c:1407)
==6051== by 0x804CECB: main (main.c:1580)

I've been allocating multidimensional arrays this way for years
(although not with structs until now), and I've never had such
issues
(although I never used Valgrind before to verify that). Would
anyone
know what's wrong with my code?

Thanks in advance.

You have failed to check your malloc()s. 3D arrays get very big
even
for
small dimensions.

Later I checked by checking all my allocations for NULL returns with
fprintf's, and I had no NULLs. If I had NULLs, wouldn't my app
sigsegv
anyways? Anyways, my array is "only" about 1.7 MB.

If any of your allocations had failed, your code would invoke
undefined behavior. There is no guarantee that the behavior would
manifest itself as a segfault. In fact, a segfault would be one of
the "better" manifestations. Unfortunately, one of the worse
manifestations is "appear to work until it is almost impossible to
find what the real problem is."

Well it sounds a hell of a lot like my problem, I must say.

How does fprintf let you know if any of the allocations failed?

lut = malloc(LUT_HC * sizeof(lut_entry **));
if (lut == NULL)
fprintf(stderr, "malloc returned null on lut\n");
for (ih=0; ih<LUT_HC; ih++)
{
lut[ih] = malloc(LUT_DC * sizeof(lut_entry *));
if (lut[ih] == NULL)
fprintf(stderr, "malloc returned null on lut[%d]\n", ih);
for (id=0; id<LUT_DC; id++)
{
lut[ih][id] = calloc(LUT_AC, sizeof(lut_entry));
if (lut[ih][id] == NULL)
fprintf(stderr, "malloc returned null on lut[%d][%d]\n", ih, id);
}
}

Is there any other code in the for loops you are not showing us?

Nope, and then if I didn't show the code with the fprintf's in the
loops it's simply because I hadn't done it yet at the time of the
original posting. By the way, am I even checking my malloc returns
properly?

If the total structure is only 1.7MB then the problem is unlikely to be a
malloc() fail.
The code seems to be correct - apart from the technical problem of not
calling exit() - but that is vanishingly unlikely to be the root error.

I suspect that in later code you are traversing the indices in the wrong
order.

If by that you mean doing lut[ia][ih][id] instead of lut[ih][id][ia]
then no, I checked every instance of my use of this array and
everything is in the correct order.
If you compile with a boundschecker it might pick it up.

How do I do that? I found a bounds checker option for gcc but it's
said it only works for fortran and java.
Try it anyway. It can't do any harm, as long as you remember that a negative
result doesn't necessarily mean no corruption.

Oh I tried, literally didn't say anything..
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top