gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > malloc: array of pointers

#172305 - Kensai - Fri Jan 29, 2010 9:56 pm

I have to malloc an array of TYPE pointers. Is the following command okay?
Code:
TYPE** arrayOfPointers = (TYPE**)malloc(numberOfElements*sizeof(TYPE*));

#172307 - Dwedit - Fri Jan 29, 2010 11:59 pm

Looks good.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."

#172405 - ninjalj - Fri Feb 05, 2010 1:00 am

Since you're doing a multiply, I'd recommend calloc, to make good habits. (calloc usually takes care of integer overflows, given a good implementation).

#172410 - sajiimori - Fri Feb 05, 2010 1:55 am

You mean if you're allocating more than 4 gigabytes?

#172411 - ninjalj - Fri Feb 05, 2010 2:11 am

Yes. For instance, if some day you work on a project where either nelem or elsize are user controlled.

Just to be clearer: if you _think_ you're allocating nelem*elsize, but in fact you're allocating (nelem*elsize) % SIZE_MAX, leading to DoS or maybe even arbitrary code execution.

As I said, I only mentioned it to create good habits for future projects.

#172418 - elwing - Fri Feb 05, 2010 8:07 am

I also find calloc clearer when reading the code... it's easier to see that you allocate an array and not just a chunk of memory. but I doubt it change much... ido even think that some platforms possible have that calloc defined as:
Code:
#define calloc(a,b) malloc(a*b)

#172429 - sajiimori - Fri Feb 05, 2010 8:42 pm

calloc initializes the array to 0, which makes me wonder: If you're allocating a 4 GB buffer, shouldn't you take a moment to consider whether you really want the kernel to swap the whole thing in, rather than being in the habit of swapping it all in by default?

I haven't done much on platforms with virtual memory, so maybe I'm misunderstanding something.

For what it's worth, this isn't an argument in favor of malloc. If anything, I'd say neither of them is particularly safe (where "safe" means I'm unlikely to screw it up, and I can look back later and easily determine whether I screwed it up).

#172432 - kusma - Fri Feb 05, 2010 10:31 pm

Claiming that calloc is safer because of integer overflow on GBAdev.org is just insane. The GBA has 256k of memory, so there's no way the multiplication overflow in reality. Worst case is a DS, where there's 4 megs of RAM. That leaves 20 bits of head-room.

#172435 - Dwedit - Sat Feb 06, 2010 12:21 am

kusma wrote:
Claiming that calloc is safer because of integer overflow on GBAdev.org is just insane. The GBA has 256k of memory, so there's no way the multiplication overflow in reality. Worst case is a DS, where there's 4 megs of RAM. That leaves 20 bits of head-room.


I was waiting for someone to point this out.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."

#172441 - elwing - Sat Feb 06, 2010 11:38 am

yep, but my argument on calloc being easier to read as "allocating an array" stands :)

#172444 - kusma - Sat Feb 06, 2010 1:08 pm

sajiimori wrote:
calloc initializes the array to 0, which makes me wonder: If you're allocating a 4 GB buffer, shouldn't you take a moment to consider whether you really want the kernel to swap the whole thing in, rather than being in the habit of swapping it all in by default?

I haven't done much on platforms with virtual memory, so maybe I'm misunderstanding something.

In THEORY, a calloc-implementation on a platform with an MMU can initialize one page of zeroed out data, and set up all pages to point to the same page with copy-on-write enabled. In reality I don't think there's any widely-used implementations that actually does this.

#172445 - kusma - Sat Feb 06, 2010 1:12 pm

elwing wrote:
yep, but my argument on calloc being easier to read as "allocating an array" stands :)

That's not as much an argument as it is a personal preference. I personally think "hmm, why does this array need to be zero-initialized?" when I read code with calloc. So unless the array needs to be zero-initialized, I'm in favor of malloc. "p=calloc(...)" is certanly a tad cleaner than "p=malloc(...); memset(p, 0, ...);".

#172449 - sajiimori - Sat Feb 06, 2010 8:44 pm

This thread is great -- the actual question was answered so quickly that we can derail it with abandon. For instance:

You know what's even easier to read?
Code:
TYPE* p = new TYPE[numberOfElements];

*waits for flamewar*

#172452 - ritz - Sun Feb 07, 2010 2:26 am

Or, something like: I like to free up my memory with a lot of beer :)

#172465 - Drovor - Mon Feb 08, 2010 4:46 pm

You can have the best of both worlds with placement new....

Code:

 TYPE* array= (TYPE*) malloc ( sizeof(TYPE) * numberOfElements );
 TYPE *t = new (&array[count++]) TYPE( );

#172468 - sajiimori - Mon Feb 08, 2010 7:31 pm

Heck yeah, that was the most readable and safe example yet. It reminds of a song, that goes something like:
Code:
std::vector v;
v.reserve(numberOfElements);
v.push_back(TYPE());

#172470 - Miked0801 - Mon Feb 08, 2010 10:32 pm

TYPE *array = (TYPE *)0x00000000;

There - all the space you want :)

#172472 - Dwedit - Mon Feb 08, 2010 10:49 pm

Miked0801 wrote:
TYPE *array = (TYPE *)0x00000000;

There - all the space you want :)

I tried that, but NO$GBA keeps giving me errors about writing to readonly memory.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."

#172473 - sajiimori - Tue Feb 09, 2010 1:51 am

Indeed -- slight correction:

const TYPE *array = (TYPE *)0x00000000;

#172492 - Miked0801 - Tue Feb 09, 2010 7:22 pm

TYPE *array = (TYPE *)random();

;)

#172495 - ritz - Tue Feb 09, 2010 7:42 pm

I hope some new guy doesn't come here looking for code examples on allocating memory. Either a post will appear in the next few days wanting help figuring out their horribly failing program... or they'll just throw in the towel forever :)

#172499 - sajiimori - Tue Feb 09, 2010 11:48 pm

Code:
try
{
  return allocateMemory();
}
catch(const Towel& t)
{
  std::cerr << "Don't stop believin'!" << std::endl;
  return (void*)std::rand();
}

#172523 - Miked0801 - Wed Feb 10, 2010 8:09 pm

lol - ftw.

I can't compete with that allocator - best ever.