LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   malloc array of pointers for platform independence (http://www.linuxquestions.org/questions/programming-9/malloc-array-of-pointers-for-platform-independence-665432/)

jiml8 08-26-2008 01:50 AM

malloc array of pointers for platform independence
 
I have a circumstance where I need to malloc an array of pointers in C++. I wish this code to be platform independent, so I need to specify the size of the array in a platform independent fashion.

On a 32 bit x86 system, the pointer size is the word size (32 bit) but I can't guarantee this is always the case.

Can anyone tell me what type is guaranteed to match the size of a pointer on any platform?

Presently I am doing it this way:

char **osltxt;
osltxt = (char **)malloc(sizeof(int)*nentries);

but I am pretty sure that I can't use sizeof(int) as my assurance of the pointer size going forward. I thought of using sizeof(char *) but I don't know if that is valid or will work across all platforms.

jlliagre 08-26-2008 03:40 AM

You can use "sizeof(void*)" to get the size of a generic pointer or in your case, "sizeof(char *)" is appropriate.

dmail 08-26-2008 05:00 AM

Quote:

Originally Posted by jiml8 (Post 3259885)
I have a circumstance where I need to malloc an array of pointers in C++. I wish this code to be platform independent, so I need to specify the size of the array in a platform independent fashion.

Well you don't really, you could use either of the following.
Code:

char ** osltxt = new char*[nentries];
std::vector<char*> osltxt(nentries,0);

If for some reason you need to use malloc then you can do as jlliagre suggested

ta0kira 08-26-2008 06:47 AM

I don't really understand the problem. You need the array to unconditionally align at the binary level on all machines, and that array needs to hold pointers to something else, such as C-strings? I'm pretty sure that's not possible unless you do something like this:
Code:

#include <stdint.h>

typedef union
{
    char    *data;
    uint64_t  alignment;
} uniform_element;

uniform_element same_everywhere[32];

Sure, that might allow alignment of the actual elements, but that seems pretty futile since the pointers might be different sizes.
ta0kira

edit:
Another option:
Code:

typedef struct { char *data; } __attribute__ ((aligned (8))) uniform_element;

dmail 08-26-2008 07:21 AM

Maybe I have misunderstood your requirement and it is as taOkira writes, yet I took the following
Quote:

Can anyone tell me what type is guaranteed to match the size of a pointer on any platform?
To mean what is the size of a pointer on any one machine it is running on, not a universal type across different architectures. As pointers on machine have no correlation to a pointer on a different machine as it has a different address space.

jiml8 08-26-2008 10:47 AM

Quote:

Originally Posted by dmail (Post 3259994)
Well you don't really, you could use either of the following.
Code:

char ** osltxt = new char*[nentries];
std::vector<char*> osltxt(nentries,0);

If for some reason you need to use malloc then you can do as jlliagre suggested

Hmmm...

My thought processes are very C-like. Though I have done work on and supported C++ programs in the past, this is the first time I have undertaken a major project in C++. I am doing it because, though it is costing me extra effort for the initial organization (due to my lack of familiarity) I do expect it to make things go a lot faster later on.

I take it that setting my array up this way automatically provides the required platform independence on pointer size? Looks like it would because there is no explicit size specified, unlike in malloc...

OK. Thanks.

From that perspective, is there a more C++ way to handle these two subsequent lines?

osltxt[n] = (char *)malloc(instring.length());
instring.copy(osltxt[n],instring.length());

It works perfectly well, but once again malloc is in play. (I like malloc and calloc :) )

dmail 08-26-2008 11:35 AM

Well for a start I would do away with the array of char pointers if the reason for the char pointers was for string and instead use an std::string and a std::vector.
Code:

std::vector<std::string> osltxt(nentries);
osltxt[n] = instring;


jiml8 08-26-2008 01:31 PM

Actually, my plan is to make osltxt static. It is buried in a class and I don't know how big it will be until the first time the class is invoked in the program.

This is a program initialization thing; this array is populated from a text file and will persist for the life of the program. The array contains the text of all messages that are posted in requesters throughout the program.

I am actually getting into a chicken and egg problem defining this as static. I want it to be a private static array but I cannot seem to get that to work. If it is static, I want to load it once then never again even if a new instance of the class is defined (which certainly will happen). Problem is that I can only define a prototype in the class if I make it static, and I have not figured out how to test for the existence of the array before I define storage for it - by which time it is too late.

I would prefer to completely avoid global variables in this program - in fact, that is a design goal - and would prefer to have "pseudo-globals" carried around in relevant classes, but it looks like I might not be able to do that given that this thing has to be defined dynamically.

If I turn this into a global array, then the mechanism you show will work just fine. Doing it in a class where it is private and static requires me to know nentries before I do know nentries, since I obtain that from the file I read in.

*sigh*

edit: Also, for this array I am better off keeping the char * organization because it is all headed for gtk, and this organization is more compatible with gtk. Saves me having to do a conversion as I send it.

ta0kira 08-26-2008 07:33 PM

I think you misunderstand how to implement a static member. You declare it as static in the class body in the header, then in the source you define it. That allows it to be private and also have a single definition. The definition will have to be in the header instead of the source if you use a template class, obviously.
Code:

//yourclass.hpp

class yourclass
{
    static int values[64];
};

Code:

//yourclass.cpp

#include "yourclass.hpp"

int yourclass::values[64];

ta0kira

jiml8 08-27-2008 01:03 AM

Ultimately, that is what I figured out. I had tried to declare it static by merely declaring the pointer to it as static, then allocating the actual array dynamically. This doesn't work.

Unfortunately, I do not know the size of the array at compile time so I either have to allocate too much space in order to be static while still retaining some upgrade capability, or I have to find another way.

So now the pointer is defined as a global pointer, and I allocate it and populate it at run time and just treat it like any other C pointer.

It'll do. Since all the data goes to gtk, keeping it as a C pointer and a C array actually makes a lot of sense.

ta0kira 08-27-2008 06:52 AM

It's often better to manually allocate and initialize global data in C++, especially when multiple threads are involved.
ta0kira

jlliagre 08-27-2008 03:02 PM

Quote:

Originally Posted by jiml8 (Post 3260357)

osltxt[n] = (char *)malloc(instring.length());
instring.copy(osltxt[n],instring.length());

It works perfectly well, but once again malloc is in play. (I like malloc and calloc :) )

Are you sure these lines work that well ?
I may be wrong as I avoid C++ as much as I can but it looks incorrect to me not to allocate one extra character for a null string terminator and not to set that character.

jiml8 08-27-2008 05:53 PM

Quote:

Originally Posted by jlliagre (Post 3261851)
Are you sure these lines work that well ?
I may be wrong as I avoid C++ as much as I can but it looks incorrect to me not to allocate one extra character for a null string terminator and not to set that character.

Good catch. I did in fact have to do that. Then I changed to code to this:

osltxt[n] = new char[instring.length()+1];

which is the c++ way.


All times are GMT -5. The time now is 06:35 AM.