How to free a pointer in a structure array? - c

I have created a structure:
struct SeqInfo
{ int Len;
int uncLen;
int *uncIndex;
char *seq;
char *seqc;
char *seqr;};
I malloc space and initialize a structure in the function:
void initSeqInfo(struct SeqInfo *SI, char *seq, char *seqc, char *seqr){
int lenTemp;
int lenUnc;
// length of the seq and uncertain
lenTemp = strlen(seq);
lenUnc = Num_uncertains(seqr);
// make space
SI->seq = (char *)malloc(sizeof(char)*lenTemp);
SI->seqc = (char *)malloc(sizeof(char)*lenTemp);
SI->seqr = (char *)malloc(sizeof(char)*lenTemp);
SI->uncIndex = (int *)malloc(sizeof(int)*lenUnc);
// init seq
SI->Len = lenTemp;
SI->uncLen = lenUnc;
// init index
Index_uncertains(seqr, SI->uncIndex);
// init seq
strcpy(SI->seq, seq);
strcpy(SI->seqc, seqc);
strcpy(SI->seqr, seqr);
}
I also define a function to free the space as follows:
// free space for structure SeqInfo
void freespace(struct SeqInfo SI){
free(SI.seq);
free(SI.seqc);
free(SI.seqr);
free(SI.uncIndex);
}
I define a pointer to the structure and initialize it as follows:
struct SeqInfo *SeqRNAs;
SeqRNAs = (struct SeqInfo*)malloc(sizeof(struct SeqInfo)*NumComb);
initSeqInfo(&SeqRNAs[0], seq10, struct10_con, struct10_req);//A1P2
initSeqInfo(&SeqRNAs[1], seq13, struct13_con, struct13_req);//A3P1
initSeqInfo(&SeqRNAs[2], seq4, struct4_con, struct4_req);//P1P4
initSeqInfo(&SeqRNAs[3], seq14, struct14_con, struct14_req);//A3P2
initSeqInfo(&SeqRNAs[4], seq17, struct17_con, struct17_req);//A4P2
initSeqInfo(&SeqRNAs[5], seq18, struct18_con, struct18_req);//A4P3
The problem occurs when I try to free the space for the defined SeqRNAs[]:
for(i = 0; i < NumComb; i++){
freespace(SeqRNAs[i]);
}
The error is:
*** glibc detected *** ./Blocks14E: free(): invalid next size (fast): 0x0000000001123210 ***
Why am I getting this error? I am pretty sure this is the only place I free the space.

You are calling strcpy() which requires a null terminator, so you need to make sure you have room for the null terminator. Your current code does not include space for the null terminator:
lenTemp = strlen(seq);
....
SI->seq = (char *)malloc(sizeof(char)*lenTemp);
....
strcpy(SI->seq, seq);
change to:
lenTemp = strlen(seq);
....
SI->seq = (char *)malloc(sizeof(char)*(lenTemp + 1));
....
strcpy(SI->seq, seq);
same for SI->seqc and SI->seqr

Note that you declare SeqRNAs as a struct SeqInfo* and allocate an array of SeqInfo (basically a constructor for the SeqRNAs[] array),
struct SeqInfo *SeqRNAs;
SeqRNAs = (struct SeqInfo*)malloc(sizeof(struct SeqInfo)*NumComb);
You will need to define a destructor to ensure you only perform a single free on SeqRNAs (example provided at end).
Then you call constructor/initializers for your SeqInfo[] elements,
initSeqInfo(&SeqRNAs[0], seq10, struct10_con, struct10_req);//A1P2
initSeqInfo(&SeqRNAs[1], seq13, struct13_con, struct13_req);//A3P1
initSeqInfo(&SeqRNAs[2], seq4, struct4_con, struct4_req);//P1P4
initSeqInfo(&SeqRNAs[3], seq14, struct14_con, struct14_req);//A3P2
initSeqInfo(&SeqRNAs[4], seq17, struct17_con, struct17_req);//A4P2
initSeqInfo(&SeqRNAs[5], seq18, struct18_con, struct18_req);//A4P3
Note that you define your constructor/intializer by passing the SeqInfo pointer (equivalent to C++' this), which should be a hint for the problem,
void initSeqInfo(struct SeqInfo *SI, char *seq, char *seqc, char *seqr);
You have defined a destructor for your SeqRNAs[] elements, but you pass the struct SeqInfo rather than a pointer (struct SeqInfo*) (remember, this is C),
void freespace(struct SeqInfo SI){
free(SI.seq);
free(SI.seqc);
free(SI.seqr);
free(SI.uncIndex);
}
Because we all want to be careful, I would suggest rewriting your destructor to add guards prior to calling free, and you need to pass SI as a pointer,
void freespace(struct SeqInfo* SI){
if(!SI) return;
if(SI->seq) free(SI->seq);
if(SI->seqc) free(SI->seqc);
if(SI->seqr) free(SI->seqr);
if(SI->uncIndex) free(SI->uncIndex);
return;
}
You probably want to declare a destructor for your SeqInfo, and you will pass each SeqRNAs[ndx] by address (use '&' to get address),
void SeqInfoDel(struct SeqInfo* SI) {
if(!SI) return;
int ndx;
for(ndx = 0; ndx < NumComb; ndx++) {
freespace(&SeqRNAs[ndx]);
}
free(SI);
}
And call this like so,
SeqInfoDel(SeqRNAs); SeqRNAs=NULL;
Note also that inside the SeqInfo constructor/initializer, you peform mallocs, but omit checking the return value (malloc fail will return NULL, and your later strcpy will fault). You might use strdup instead. Or build a convenience function that allocates the string of the specified size and copies enough space, ergo,
char*
strsizedup(size_t len, char* src) {
//handle len<=0?
char* p = malloc(sizeof(char)*(len+1));
if(!p) return(p);
strncpy(p,src,len); p[len]='\0';
return(p);
}
And rewrite your SeqInfo constructor/initializer to use this convenience function.
void initSeqInfo(struct SeqInfo *SI, char *seq, char *seqc, char *seqr){
int lenTemp;
int lenUnc;
// length of the seq and uncertain
lenTemp = strlen(seq);
lenUnc = Num_uncertains(seqr);
SI->Len = lenTemp;
// make space
SI->seq = strsizedup(lenTemp,seq);
SI->seqc = strsizedup(lenTemp,seqc);
SI->seqr = strsizedup(lenTemp,seqr);
SI->uncIndex = (int *)malloc(sizeof(int)*lenUnc);
SI->uncLen = lenUnc;
// init index
Index_uncertains(seqr, SI->uncIndex);
}
Note that the above function still has problems when any of seq, seqc, seqr are NULL, and may have semantic errors when len(seq) != len(seqc) != len(seqr).

Related

How to malloc an array of structures [duplicate]

This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 6 years ago.
I would like to know how to malloc (and hen realloc) an array of a structure.
Here is my structure :
typedef struct tag {
char *key;
char *val;
} tag;
I use this structure in another structure :
typedef struct node {
int id;
double lat;
double lon;
int visible;
tag *tab;
} node;
I define a node *n, then:
n->tab = (tag*)malloc(sizeof(tag) * 5);
but I have an error of malloc corruption.
void remplisTag(xmlNodePtr cur, node *n) {
xmlNodePtr fils;
n->tab = malloc(sizeof(*n->tab) * 5);
if (n->tab == NULL) {
error(E_ERROR_MALLOC);
}
printf("apres malloc\n");
int taille = 5;
int ind = 0;
xmlAttrPtr attr1, attr2;
xmlChar *key;
xmlChar *value;
fils = cur->xmlChildrenNode;
fils = fils->next;
while (xmlStrcmp(fils->name, (const xmlChar*)"text") != 0) {
if (xmlStrcmp(fils->name, (const xmlChar*)"tag") == 0) {
if (ind == taille - 1) {
n->tab = realloc(n->tab, sizeof(tag) * (taille + 5));
taille = taille + 5;
} else {
taille = taille;
}
/* searching for key */
attr1 = xmlHasProp(fils, (const xmlChar*)"k");
if (attr1 == NULL) {
error(E_KEY);
} else {
key = xmlGetProp(fils, (const xmlChar*)"k");
if (key == NULL) {
error(E_KEY_V);
}
/* searching for value */
attr2 = xmlHasProp(fils, (const xmlChar*)"v");
if (attr2 == NULL) {
error(E_VALUE);
}
value = xmlGetProp(fils, (const xmlChar*)"v");
if (value == NULL) {
error(E_VALUE_V);
}
tag t;
t.key = malloc(sizeof((char*)key));
strcpy(t.key, (char*)key);
strcpy(t.val, (char*)value);
t.val = malloc(sizeof((char*)value));
n->tab[ind++] = t;
}
}
fils = fils->next;
}
free(n->tab);
}
In main:
node *n = malloc(sizeof(node));
xmlNodePtr cur;
in a while loop:
remplisTag(cur, n);
There is a memory allocation issue in the following lines
tag t;
t.key = malloc(sizeof((char*)key));
strcpy(t.key, (char*)key);
strcpy(t.val, (char*)value);
t.val = malloc(sizeof((char*)value));
The memory in C is very fiddly - when you allocate memory, you need to hold enough to store the data.
tag t;
t.key = malloc(sizeof((char*)key));
strcpy(t.key, (char*)key);
Creates enough for a pointer -which is probably not enough.
The fix is something like.
tag t;
t.key = strdup( key );
t.val = strdup( value );
The strdup function combines the malloc (of the correct size) and the strcpy.
There is no visible problem in your allocation statement, some people prefer that malloc() return value not be cast to the destination type, and it is slightly more reliable to use the type of the destination pointer to avoid type mismatches that would be hard to detect:
n->tab = malloc(sizeof(*n->tab) * 5);
What is the precise error message you get?
Is it a runtime error?
How did you allocate the node structure that n points to?
Can you post the full code to the function that produces this failure?
A runtime message from malloc() is an indication that the memory allocation structures used internally by malloc have been corrupted. It would indicate that the problem is elsewhere, probably a buffer overrun in another object allocated by malloc(). Check the code that was executed since the previous call to malloc().
EDIT:
In the code posted, there are some allocation errors:
t.key = malloc(sizeof((char*)key));
strcpy(t.key, (char*)key);
strcpy(t.val, (char*)value);
t.val = malloc(sizeof((char*)value));
The space you allocate is just the size of a pointer char*, not the length of the string plus 1 for the final null terminator. If key is longer than 3 or 7 bytes, depending on the architecture, you have a buffer overrun.
t.val is allocated after you copy contents to it. Undefined behavior!
You should simplify this with strdup():
t.key = strdup((char*)key);
t.val = strdup((char*)value);
Your test for reallocation is too conservative: the array should be reallocated when ind == taille:
if (ind == taille) {
n->tab = realloc(n->tab, sizeof(*n->tab) * (taille + 5));
taille += 5;
}
taille and ind should be stored into the node to keep track of how much space has been allocated and how many tags are present. The current code does not provide this information to the caller, the rest of the tag array is uninitialized, there is no way to tell, undefined behavior is lurking.
Note that there are too many casts in your code. Casts prevent some type mismatch detection by the compiler, it is wise to change the argument types for your functions to avoid unnecessary casts.
For example: libxml2 defines xmlChar as a typedef for unsigned char. This is a very bad design decision. They should use char and handle the strings correctly regardless of whether char happens to be signed or unsigned on the current environment. This choice forces programmers to cast most arguments to the xmlXXX APIs, making the code ugly and error prone. You cannot change that, but you could use inline functions to convert between char* and xmlChar* to keep casts to a minimum.

how to use a static struc into a static function ? ( like a global )

for the need of my project i need to handle a global (representing the heap ). It's a C project, i don't have any errors at the compilation.
but when i try to use a member of struct -> segfault.
if someone could tell me where is the point ?
thanks
static t_meta *init_get_meta()
{
static t_meta *allineed = NULL;
int i;
i = 0;
if (allineed == NULL)
{
//allineed->pagesize = getpagesize();
//allineed->pagesize = 4096;
allineed->pagesize = 0; --> segfault right here
printf("LOVE\n");
while (i < 8)
{
allineed->listfree[i++] = NULL;
}
allineed->last = extend_heap(allineed);
}
return (allineed);
}
You are de-referencing a NULL pointer.
Here in this line of code you check for NULL and go ahead and access that memory which is illegal.
if (allineed == NULL)
allineed->pagesize = 0; // incorrect at this time allineed is pointing to 0x0
What you need to do is malloc the structure and than check if malloc returned with not a NULL value. something on the lines of
static t_meta *allineed = malloc(sizeof(t_meta));
if (allineed)
{
//do something
}
else
//return error
You might want to look at these questions if you are trying to implement a basic malloc yourself
How do malloc() and free() work?
How is malloc() implemented internally?
A very basic malloc would do these basic steps
void * my_malloc(size_t size)
{
size_t headersize = 1; // 1 byte header
uint8_t alignment = 8; // 8 byte alignment
// the block should be 8 bytes align
size_t alloc_size = ((size+1)+(alignment-1))&~(alignment-1);
//use system call
void *head = sbrk(alloc_size );
if(head == (void *)(-1))
return NULL;
//update the header here to mark the size and other bits depending upon req
char *header_val = (char *)head;
*header_val = (alloc_size/2) | ( 1 << 7);//only support power 2 sizes
//return updated pointer location to point to ahead of header
// after changing the pointer to char type as pointer arithmetic is not allowed on void pointers
//printf("allocated size is %d with first byte %p\n",alloc_size,header_val);
//printf(" %02x\n",(unsigned char)*(char *)header_val);
return (char *)head + headersize;
}

C Pointer and Memory Allocation: Realloc Arrays and Pointer Passing

For those experienced with C, this will be a simple memory allocation/referencing problem:
Here are my data structures:
struct configsection {
char *name;
unsigned int numopts;
configoption *options;
};
typedef struct configsection configsection;
struct configfile {
unsigned int numsections;
configsection *sections;
};
typedef struct configfile configfile;
Here are my routines for initializing a configsection or configfile, and for adding a configsection to a configfile:
// Initialize a configfile structure (0 sections)
void init_file(configfile *cf) {
cf = malloc(sizeof(configfile));
cf->numsections = 0;
}
// Initialize a configsection structure with a name (and 0 options)
void init_sec(configsection *sec, char *name) {
sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
}
// Add a section to a configfile
void add_sec(configfile *cf, configsection *sec) {
// Increase the size indicator by 1
cf->numsections = cf->numsections + 1;
// Reallocate the array to accommodate one more item
cf->sections = realloc(cf->sections, sizeof(configsection)*cf->numsections);
// Insert the new item
cf->sections[cf->numsections] = *sec;
}
I believe my problem originates in my init_sec() function. Here is an example:
int main(void) {
// Initialize test configfile
configfile *cf;
init_file(cf);
// Initialize test configsections
configsection *testcs1;
init_sec(testcs1, "Test Section 1");
// Try printing the value that should have just been stored
printf("test name = %s\n", testcs1->name);
Although the printf() in init_sec() successfully prints the name I just stored in the configsection, attempting the same thing in the printf() of main() produces a segmentation fault. Further, addsec() produces a segmentation fault.
This routine should be
void init_file(configfile **cf) {
*cf = malloc(sizeof(configfile));
(*cf)->numsections = 0;
(*cf)->sections = NULL; // You forgot to initialise this.
}
i.e. called by init_file(&myconfigfilepointer); so the malloc return value gets passed back.
Need to do the same trick for init_sec
This function is incorrect - here is a corrected version
void add_sec(configfile *cf, configsection *sec) {
// Increase the size indicator by 1
// Reallocate the array to accommodate one more item
cf->sections = realloc(cf->sections, sizeof(configsection)*(1 + cf->numsections));
// Insert the new item
cf->sections[cf->numsections] = *sec; // Since arrays start at 0
cf->numsections = cf->numsections + 1;
}
You then need to adjust the calls in main
At no point do you initialise cf->sections, which means when you try to realloc it the first time, you're passing rubbish. Adding:
cf->sections = NULL;
to init_file should help.
You're also not checking any return codes, but you knew that yes?
You need to pass a pointer of the value to be updated... eg:
// Initialize a configfile structure (0 sections)
void init_file(configfile **cf) {
*cf = malloc(sizeof(configfile));
(*cf)->numsections = 0;
}
configfile *var;
init_file(&var);
printf("%d\n", var->numsections);
Otherwise you are just updating the local pointer *cf and not the original passed in value
You need to really rethink how function arguments are passed in C and what pointers are. Your problem has nothing to do with memory allocation. Rather, your code is assigning a pointer to dynamically allocated memory only to a local variable, of which the calling code knows nothing.
While you could solve the problem by passing a pointer to the caller's pointer (i.e. a double pointer), this is not necessarily the most elegant or most usual way of handling things. Rather, you should return the result of the allocation from the function. While you're at it, you should also use calloc to zero out the memory right away. Wrapping it all up:
typedef struct substuff_
{
int a;
double b;
} substuff;
typedef struct stuff_
{
unsigned int n;
substuff * data;
} stuff;
substuff * init_substuff()
{
substuff * const p = malloc(sizeof *p);
if (p) { p->a = 5; p->b = -0.5; }
return p;
}
stuff * init_stuff()
{
substuff * const p = init_substuff();
if (!p) return NULL;
stuff * const q = malloc(sizeof *q);
if (q) { q->n = 10; q->data = p; }
return q;
}
As an exercise, you should write the corresponding functions void free_substuff(substuff *) and void free_stuff(stuff *).
Yes, there is a problem in init_sec
// Initialize a configsection structure with a name (and 0 options)
void init_sec(configsection *sec, char *name) {
sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
}
You're just copying the name pointer here, which means, that it points to the original storage of name. If you'd call init_sec like this
configsection foobar()
{
configsection sec;
char name[80];
get_name(name);
init_sec(sec, name);
return sec;
}
The name pointer became invalid the moment foobar returned. You need to duplicate the string and keep your private copy around. In init_sec:
sec->name = strdup(name);
But there's more. In the very first line of init_sec you're overwriting the pointer that was passed to init_sec with the one of malloc. So the new pointer never gets passed back to the calle. Either use a pointer to a pointer, don't take a configsection pointer at all (after all, you're allocating), but just return the allocated pointer: Complete corrected function:
// Initialize a configsection structure with a name (and 0 options)
configsection* init_sec(char *name) {
configsection *sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
return sec;
}

C programming pointers and char array problems

I want to pass the contents of an array to another method and have that method print out the entire array - how would i do this?
Currently:
I'm returning an array from a function.
char* search_value(struct PDB *llist)
{
int realID = -7;
int x = 0;
int task = 0;
char *received;
char theMessage[100];
theMessage[0] = '\0';
printf("Your choice: `Search'\n");
printf("Enter the value you want to find: ");
scanf("%d", &task);
while(llist->data1 != NULL)
{
if(task == llist->taskID)
{
realID = llist->taskID;
strcpy(theMessage, llist->data1);
break;
}
}
return theMessage;
}
i'm getting the return value:
void getMessage(const int GET_MESSAGE)
{
char * received = NULL;
int x = 0;
received = search_value(llist);
printf("%s", received);
}
I want to somehow print the entire value (rather than just the first value to which the pointer is pointing at - how would i do this?
A few corrections and it should work:
// - struct contents shouldn't be changed by the function, make its pointer const.
// - pass a pointer to an allocated array as parameter
char* search_value(const struct PDB *llist, char* theMessage)
{
int realID = -7;
int x = 0;
int task = 0;
char *received;
theMessage[0] = '\0';
printf("Your choice: `Search'\n");
printf("Enter the value you want to find: ");
scanf("%d", &task);
while(llist->data1 != NULL)
{
if(task == llist->taskID)
{
realID = llist->taskID;
strcpy(theMessage, llist->data1);
break;
}
}
return theMessage;
}
void getMessage(const int GET_MESSAGE)
{
char received[100]; // allocate the array outside the function
int x = 0;
search_value(llist, received); // pass a pointer to the first element
printf("%s", received);
}
You have an issue with variable scope here: theMessage is local to the function search_value, so you're returning a pointer to an array which no longer exists once the function completes.
Instead you should use malloc() to allocate the space for theMessage and then subsequently free() it later on outside of the function when you're finished with it —  however this can often lead to memory leaks if you're not diligent about cleaning up after yourself.
You can allocate the memory like so:
char * message = malloc(100);
One alternative would be to allocate the buffer in getMessage() and pass a pointer to the buffer into search_value which could then write into it:
void getMessage(const int GET_MESSAGE)
{
char received[100];
int x = 0;
search_value(llist, received);
printf("%s", received);
}
void search_value(struct PDB *llist, char * buffer)
{
// write to buffer
}
Another option is to declare a char * pointer inside getMessage(), pass a pointer to a pointer into search_value() and again use malloc() to allocate space for the buffer.
Finally, this is a minor style criticism, but you'd do well to learn to stick to one convention for naming your functions, search_value and getMessage are not consistent names, and this will irk many a coder that you work with.
You have several problems with your code. I'm guessing that you want to search a list for some value, then return that value.
The first problem is that you do not actually iterate over the list, but only check the same item over and over again. The other problem is that you return a pointer to a local variable. This is undefined behavior, because as soon as the function returns the memory the pointer points to can be used for something else.
I suggest you change your code as follows:
char *search_value(struct PDB *llist, char *theMessage, size_t theMessageMaxLength)
{
int realID = -7;
int task = 0;
printf("Your choice: `Search'\n");
printf("Enter the value you want to find: ");
scanf("%d", &task);
while(llist != NULL && llist->data1 != NULL)
{
if(task == llist->taskID)
{
realID = llist->taskID;
strncpy(theMessage, llist->data1, theMessageMaxLength);
theMessage[theMessageMaxLength] = '\0';
break;
}
llist = llist->next; /* Assuming the field is named "next" */
}
return theMessage;
}
void getMessage(const int GET_MESSAGE)
{
char *received = NULL;
char theMessage[100];
/* Subtract 1 from the size, for the terminating '\0' */
received = search_value(llist, theMessage, sizeof(theMessage) - 1);
printf("%s", received);
}
the array you are returning is local to that function. Either the calle function shall provide the array in which it expects the values or use static array.

How to overwrite an array of char pointers with a larger list of char pointers?

My function is being passed a struct containing, among other things, a NULL terminated array of pointers to words making up a command with arguments.
I'm performing a glob match on the list of arguments, to expand them into a full list of files, then I want to replace the passed argument array with the new expanded one.
The globbing is working fine, that is, g.gl_pathv is populated with the list of expected files. However, I am having trouble copying this array into the struct I was given.
#include <glob.h>
struct command {
char **argv;
// other fields...
}
void myFunction( struct command * cmd )
{
char **p = cmd->argv;
char* program = *p++; // save the program name (e.g 'ls', and increment to the first argument
glob_t g;
memset(&g, 0, sizeof(g));
g.gl_offs = 1;
int res = glob(*p++, GLOB_DOOFFS, NULL, &g);
glob_handle_res(res);
while (*p)
{
res = glob(*p, GLOB_DOOFFS | GLOB_APPEND, NULL, &g);
glob_handle_res(res);
}
if( g.gl_pathc <= 0 )
{
globfree(&g);
}
cmd->argv = malloc((g.gl_pathc + g.gl_offs) * sizeof *cmd->argv);
if (cmd->argv == NULL) { sys_fatal_error("pattern_expand: malloc failed\n");}
// copy over the arguments
size_t i = g.gl_offs;
for (; i < g.gl_pathc + g.gl_offs; ++i)
cmd->argv[i] = strdup(g.gl_pathv[i]);
// insert the original program name
cmd->argv[0] = strdup(program);
** cmd->argv[g.gl_pathc + g.gl_offs] = 0; **
globfree(&g);
}
void
command_free(struct esh_command * cmd)
{
char ** p = cmd->argv;
while (*p) {
free(*p++); // Segfaults here, was it already freed?
}
free(cmd->argv);
free(cmd);
}
Edit 1: Also, I realized I need to stick program back in there as cmd->argv[0]
Edit 2: Added call to calloc
Edit 3: Edit mem management with tips from Alok
Edit 4: More tips from alok
Edit 5: Almost working.. the app segfaults when freeing the command struct
Finally: Seems like I was missing the terminating NULL, so adding the line:
cmd->argv[g.gl_pathc + g.gl_offs] = 0;
seemed to make it work.
argv is an array of pointers of char *. This means that argv has space for argc char * values. If you try to copy more than that many char * values into it, you will end up with an overflow.
Most likely your glob call results in more than argc elements in gl_pathv field (i.e, gl_pathc > argc). This is undefined behavior.
It is similar to the code below:
/* Wrong code */
#include <string.h>
int a[] = { 1, 2, 3 };
int b[] = { 1, 2, 3, 4 };
memcpy(a, b, sizeof b);
Solution: you should either work with the glob_t struct directly, or allocate new space to copy gl_pathv to a new char **:
char **paths = malloc(g.gl_pathc * sizeof *paths);
if (paths == NULL) { /* handle error */ }
for (size_t i=0; i < g.gl_pathc; ++i) {
/* The following just copies the pointer */
paths[i] = g.gl_pathv[i];
/* If you actually want to copy the string, then
you need to malloc again here.
Something like:
paths[i] = malloc(strlen(g.gl_pathv[i] + 1));
followed by strcpy.
*/
}
/* free all the allocated data when done */
Edit: after your edit:
cmd->argv = calloc(g.gl_pathc, sizeof(char *) *g.gl_pathc);
it should work, but each of argv[1] to argv[g.gl_pathc + g.gl_offs - 1] is a char * that is "owned" by the struct glob. Your memcpy call is only copying the pointers. When you later do globfree(), those pointers don't mean anything anymore. So, you need to do copy the strings for your use:
size_t i;
cmd->argv = malloc((g.gl_pathc+g.gl_offs) * sizeof *cmd->argv);
for (i=g.gl_offs; i < g.gl_pathc + g.gl_offs; ++i)
cmd->argv[i] = strdup(g.gl_pathv[i]);
This makes sure you now have your own private copies of the strings. Be sure to free them (and argv) once you are done.
There are a few other problems with your code.
You are doing *p++, you should do p++, since you're not using the value of the dereferencing.
You should really check the return value of glob.
Your paths variable needs g.gl_pathc + 1 elements, not g.gl_pathc. (Or more correctly, you need to allocate g.gl_pathc + g.gl_offs times sizeof *paths bytes.)
Your for loop to copy strings should be for (j=1; j < g.gl_pathc + g.gl_offs; ++j).
Make sure you prevent shell from expanding your glob. I.e., call ./a.out '*' instead of ./a.out *.
Don't you need to multiple g.gl_pathc by sizeof(char *)?

Resources