I am trying to read a directory using the Dirent Header file in C.
I am having trouble storing the file names inside the given directory inside a char array.
the code is below.
char * FileNames;
while ( ( DirentPointer = readdir(DirectoryPointer) ) != NULL) {
strcpy(&FileNames[Counter], DirentPointer -> d_name);
Counter++;
}
When I run the application I am getting a segmentation fault. I think that the strcpy is faulting the application because of memory allocations.
Can anyone tell me how malloc and realloc can be used to dynamically add memory allocation to the FileNames Char *?
Your code would produce undefined behaviour or most probably crash. That's because FileNames is a pointer to a character, not to a memory buffer to copy your strings into and the function strcpy does not do bounds checking for the buffer being copied into. So strcpy will try to write into the memory you have not allocated for the purpose. You need to allocate memory to copy the file names first.
#define MAX_FILE_NUM 1000
char *FileNames[MAX_FILE_NUM] = {0}; // initialize to NULL
int Counter = 0;
while((DirentPointer = readdir(DirectoryPointer)) != NULL) {
FileNames[counter] = malloc(strlen(DirentPointer->d_name) + 1); // + 1 for the null byte
// check for NULL
if(FileNames[i] != NULL) {
strcpy(FileNames[i], DirentPointer->d_name);
Counter++;
}
else {
// handle the NULL case
// maybe try malloc again
}
}
// after you are done with the FileNames
for(int i = 0; i < Counter; i++) {
free(FileNames[i]);
FileNames[i] = NULL;
}
Related
Currently learning memory management in C, and I am currently running into issues increasing string length as a loop iterates.
The method I am trying to figure out logically works like this:
// return string with "X" removed
char * notX(char * string){
result = "";
if(for int = 0; i < strlen(string); i++){
if (string[i] != 'X') {
result += string[i];
}
}
return result;
}
Simple enough to do in other languages, but managing the memory in C makes it a bit challenging. Difficulties I run into is when I use malloc and realloc to initialize and change size of my string. In my code I currently tried:
char * notX(char * string){
char* res = malloc(sizeof(char*)); // allocate memory for string of size 1;
res = ""; // attempted to initialize the string. Fairly certain this is incorrect
char tmp[2]; // temporary string to hold value to be concatenated
if(for int = 0; i < strlen(string); i++){
if (string[i] != 'X') {
res = realloc(res, sizeof(res) + sizeof(char*)); // reallocate res and increasing its size by 1 character
tmp[0] = string[i];
tmp[1] = '\0';
strcat(res, tmp);
}
}
return result;
}
Note, I have found success in initializing result to be some large array like:
char res[100];
However, I would like to learn how to address this issue with out initializing an array with a fixed size since that might potentially be wasted memory space, or not enough memory.
realloc needs the number of bytes to allocate. size is incremented for each character added to res. size + 2 is used to provide for the current character being added and the terminating zero.
Check the return of realloc. NULL means a failure. Using tmp allows the return of res if realloc fails.
char * notX(char * string){
char* res = NULL;//so realloc will work on first call
char* tmp = NULL;//temp pointer during realloc
size_t size = 0;
size_t index = 0;
while ( string[index]) {//not the terminating zero
if ( string[index] != 'X') {
if ( NULL == ( tmp = realloc(res, size + 2))) {//+ 2 for character and zero
fprintf ( stderr, "realloc problem\n");
if ( res) {//not NULL
res[size] = 0;//terminate
}
return res;
}
res = tmp;//assign realloc pointer back to res
res[size] = string[index];
++size;
}
++index;//next character
}
if ( res) {//not NULL
res[size] = 0;//terminate
}
return res;
}
2 main errors in this code:
the malloc and the realloc function with parameter that call sizeof(char*). In this case the result of sizeof(char*) is the size of a pointer, not of a char, so you have to substitute the char* with char in the sizeof function.
res = ""; is incorrect. You primarly have a memory leak because you lose the pointer to the just allocated memory in malloc function, secondary but not less important, you have an undefined behavior when call realloc function over res initialized as an empty string ( or better a constant string), after the above initialization the memory is no longer dinamically managed. To substitute this initialization i think a memset to 0 is the best solution.
I am trying to get string of numbers and put it inside an int array.
I have no idea how many numbers I am going to get so I need to use dynamic allocation.
I created an array by using malloc and tried to resize it by +1 every time inside the loop.
This is my code
void main()
{
char *s;
int *polyNums;
int count = 0;
char *token;
s = gets();
polyNums = (int *)malloc(sizeof(int));
if (polyNums == NULL)
{
printf("Could not allocate required memory\n");
exit(1);
}
token = strtok(s, " ");
while (token != NULL)
{
polyNums[count] = *token - '0';
count++;
polyNums = realloc(polyNums, count+1);
token = strtok(NULL, " ");
}
}
My problem is that every time it's doing realloc, all the saved numbers are gone, if my string is "1 2 3" so in loop 1 the polyNums[0] is 1, but I am loosing it in loop 2 after reallocating. Can some one please tell me where I went wrong?
You do not allocate enough memory for your array.
int *polyNums; // Holding integer!
int count = 0;
polyNums = (int *)malloc(sizeof(int)); // enough space for interger. OK!
...
while(...)
{
polyNums[count] = *token - '0';
count++;
polyNums = realloc(polyNums, count+1); // Not enough space for intergers!
...
}
You access an array holding int values but you only allocate 1 byte per element.
While your first allocation can hold the first integer, you allocate less memory for any forther number.
polyNums = realloc(polyNums, (count+1)*sizeof(*polyNums));
Aside from that:
Do not cast the return value of malloc
Do not assign the return value of realloc directly to your pointer. In case of NULL return value you lose your old data.
You should take a look at pointers and resource management, more specifically you should learn what deep copy is and how to reallocate dynamic memory.
In general, you should define a temporary pointer for the new larger chunk of memory, copy all the old values to the new memory location and then you can reassign the temporary pointer to the initial pointer, polyNums. Then you are safe to add more new data.
So I have the following question:
I have this struct ListAut
struct ListAut{
char* biggestn;
int sizeof_biggestn;
int total_len;
struct node* avl;
};
Its typedef is as it follows:
typedef struct ListAut *IndexOfAuts;
IndexOfAuts *newIndexOfAuts()
{
int i;
IndexOfAuts *ioa = malloc(27 * sizeof(struct ListAut));
for (i = 0; i < 27; i++)
{
ioa[i]->biggestn = "";
ioa[i]->sizeof_biggestn = 0;
ioa[i]->total_len = 0;
ioa[i]->avl = NULL;
}
return ioa;
}
void insertName(IndexOfAuts * ioa, char *nome)
{
char *aux = malloc(sizeof(nome));
aux = trim(nome);
int index = getIndexOfLetter(aux);
if (nameLen(aux) > getSizeOfLongName(ioa[index]))
{
strcpy(ioa[index]->biggestn, aux);
ioa[index]->sizeof_biggestn = nameLen(aux);
}
ioa[index]->total_len += nameLen(aux);
insert(ioa[index]->avl, aux);
}
This is an important part of a module I need for a project, and on its main it's Seg Faulting. I suspect it's on the creation of an "object" newIndexOfAuts(),
The idea of this module is to have an array of 27 pointers to those structures, one to each letter and another to the special characters;
Now I'm just confused because it might be from the problem above or from a module loader I made:
void loadModules(char *filename, IndexOfAuts * ioa, StatTable st)
{
char *nameofile = malloc(20);
strcpy(nameofile, filename);
FILE *file = fopen(nameofile, "r");
if (file != NULL)
{
int counter, ano;
char *buff, *field, *auxil;
buff = malloc(1024);
field = malloc(200);
auxil = malloc(200);
while (fgets(buff, 1024, file))
{
counter = 0;
field = strtok(buff, ",");
printf("inserting 1st name\n");
insertName(ioa, field);
counter++;
while (!atoi(field))
{
if ((auxil = strtok(NULL, ",")) != NULL)
{
counter++;
field = auxil;
insertName(ioa, field);
}
}
ano = atoi(field);
incPub(st, ano, counter - 1);
}
fclose(file);
}
}
When i run this in main that has the following lines:
printf("Creating Stat Table");
StatTable st=newStatTable();\\This Line is correct, i checked it,i hope
printf("Creating index");
IndexOfAuts* ioa=newIndexOfAuts();
printf("Loading Modules");
loadModules(filename,ioa,st);
Those prints were for me to see where was the cause of the seg fault, but the last line printed was the "Creating Index".
There are several cases of undefined behavior and one memory leak (and a possible case of undefined behavior too):
You have this initialization ioa[i]->biggestn=""; It make the biggestn member point to a constant array of one character (the '\0' character). You then do strcpy(ioa[index]->biggestn,aux); which will write over a constant character, and then go outside of the array writing into unknown memory.
You have this: char* aux=malloc(sizeof(nome)); That allocates only 4 or 8 bytes, which the size of the pointer and not what the pointer points to. Use strlen to get the length of a string.
For the above allocation you also need to allocate a byte extra, as strlen only returns the length of the string without the terminator.
You have aux=trim(nome); This overwrites the pointer you just allocated, leading to a memory leak.
The above call might also lead to undefined behavior if you return a pointer to a local variable or array.
There are probably other problematic lines, these were just the ones I found on a quick glance.
And a general tip: Learn to use a debugger! The debugger is a programmers best tool next to the compiler. If you run your program in a debugger, the debugger will stop at the location of the crash, and let you examine (and also walk up) the function call stack, as well as let you examine values of variables.
While working on a program which requires frequent memory allocation I came across behaviour I cannot explain. I've implemented a work around but I am curious to why my previous implementation didn't work. Here's the situation:
Memory reallocation of a pointer works
This may not be best practice (and if so please let me knwow) but I recall that realloc can allocate new memory if the pointer passed in is NULL. Below is an example where I read file data into a temporary buffer, then allocate appropriate size for *data and memcopy content
I have a file structure like so
typedef struct _my_file {
int size;
char *data;
}
And the mem reallocation and copy code like so:
// cycle through decompressed file until end is reached
while ((read_size = gzread(fh, buf, sizeof(buf))) != 0 && read_size != -1) {
// allocate/reallocate memory to fit newly read buffer
if ((tmp_data = realloc(file->data, sizeof(char *)*(file->size+read_size))) == (char *)NULL) {
printf("Memory reallocation error for requested size %d.\n", file->size+read_size);
// if memory was previous allocated but realloc failed this time, free memory!
if (file->size > 0)
free(file->data);
return FH_REALLOC_ERROR;
}
// update pointer to potentially new address (man realloc)
file->data = tmp_data;
// copy data from temporary buffer
memcpy(file->data + file->size, buf, read_size);
// update total read file size
file->size += read_size;
}
Memory reallocation of pointer to pointer fails
However, here is where I'm confused. Using the same thought that reallocation of a NULL pointer will allocate new memory, I parse a string of arguments and for each argument I allocate a pointer to a pointer, then allocate a pointer that is pointed by that pointer to a pointer. Maybe code is easier to explain:
This is the structure:
typedef struct _arguments {
unsigned short int options; // options bitmap
char **regexes; // array of regexes
unsigned int nregexes; // number of regexes
char *logmatch; // log file match pattern
unsigned int limit; // log match limit
char *argv0; // executable name
} arguments;
And the memory allocation code:
int i = 0;
int len;
char **tmp;
while (strcmp(argv[i+regindex], "-logs") != 0) {
len = strlen(argv[i+regindex]);
if((tmp = realloc(args->regexes, sizeof(char **)*(i+1))) == (char **)NULL) {
printf("Cannot allocate memory for regex patterns array.\n");
return -1;
}
args->regexes = tmp;
tmp = NULL;
if((args->regexes[i] = (char *)malloc(sizeof(char *)*(len+1))) == (char *)NULL) {
printf("Cannot allocate memory for regex pattern.\n");
return -1;
}
strcpy(args->regexes[i], argv[i+regindex]);
i++;
}
When I compile and run this I get a run time error "realloc: invalid pointer "
I must be missing something obvious but after not accomplishing much trying to debug and searching for solutions online for 5 hours now, I just ran two loops, one counts the numbers of arguments and mallocs enough space for it, and the second loop allocates space for the arguments and strcpys it.
Any explanation to this behaviour is much appreciated! I really am curious to know why.
First fragment:
// cycle through decompressed file until end is reached
while (1) {
char **tmp_data;
read_size = gzread(fh, buf, sizeof buf);
if (read_size <= 0) break;
// allocate/reallocate memory to fit newly read buffer
tmp_data = realloc(file->data, (file->size+read_size) * sizeof *tmp_data );
if ( !tmp_data ) {
printf("Memory reallocation error for requested size %d.\n"
, file->size+read_size);
if (file->data) {
free(file->data)
file->data = NULL;
file->size = 0;
}
return FH_REALLOC_ERROR;
}
file->data = tmp_data;
// copy data from temporary buffer
memcpy(file->data + file->size, buf, read_size);
// update total read file size
file->size += read_size;
}
Second fragment:
unsigned i; // BTW this variable is already present as args->nregexes;
for(i =0; strcmp(argv[i+regindex], "-logs"); i++) {
char **tmp;
tmp = realloc(args->regexes, (i+1) * sizeof *tmp );
if (!tmp) {
printf("Cannot allocate memory for regex patterns array.\n");
return -1;
}
args->regexes = tmp;
args->regexes[i] = strdup( argv[i+regindex] );
if ( !args->regexes[i] ) {
printf("Cannot allocate memory for regex pattern.\n");
return -1;
}
...
return 0;
}
A few notes:
the syntax ptr = malloc ( CNT * sizeof *ptr); is more robust than the sizeof(type) variant.
strdup() does exactly the same as your malloc+strcpy()
the for(;;) loop is less error prone than a while() loop with a loose i++; at the end of the loop body. (it also makes clear that the loopcondition is never checked)
to me if ( !ptr ) {} is easyer to read than if (ptr != NULL) {}
the casts are not needed and sometimes unwanted.
I am mallocing an array of c strings. After releasing it, I get the following error:
Assembler(87536) malloc: *** error for object 0x108500840: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Why is that? I am pretty sure I am doing the malloc correctly. I'm pretty experienced with memory management, but I am not sure why this is giving me an error. The array is should hold three strings, each of which is 2 characters long.
Here is how I am mallocing the array:
char **reg_store;
reg_store = malloc(3 * (sizeof(char*)));
if (reg_store == NULL) {
fprintf(Out, "Out of memory\n");
exit(1);
}
for (int i = 0; i < 3; i++) {
reg_store[i] = malloc(2 * sizeof(char));
if (reg_store[i] == NULL) {
fprintf(Out, "Out of memory\n");
exit(1);
}
}
Here is how I am freeing it:
for (int i = 0; i < 3; i++) {
free(reg_store[i]);
}
free(reg_store);
Here is what I have in between:
// Keeps a reference to which register has been parsed for storage
int count = 0;
char *reg = NULL;
char *inst_ptr // POINTS TO SOME STRING. EXAMPLE: $t2, $t1, $a0
while (1) {
// Parses the string in inst_ptr with dollar, comma and space as a delimiter.
reg = parse_token(inst_ptr, " $,\n", &inst_ptr, NULL);
if (reg == NULL || *reg == '#') {
break;
}
reg_store[count] = reg;
count++;
free(reg);
}
I am printing out reg after I call parse_token and it does print out correctly. I am also printing out reg_store[count] and it does also print out correctly.
Your problem is here:
reg_store[count] = reg;
free(reg);
and later
free(reg_store[i]);
reg is already freed and you free it another time (not talking about the problems with using it later). to fix this replace
reg_store[count] = reg;
with
strcpy(reg_store[count], reg);
or as suggested in the comments, since you know its two charaters, its better to memcpy it:
memcpy(reg_store[count], reg, 2);
I would suggest adding some printfs (or use the debugger) to see the values of all the malloced pointers just after they have been malloced. Then do the same just before they are freed, to make sure they are the same. Perhaps there is some other rogue code elsewhere in the program that is stomping over memory.
Your problem is in the "in between" code, in particular, right here:
reg_store[count] = reg;
count++;
free(reg);
You allocated reg_store[count] with malloc during your set up, then you overwrite the allocated value with reg and then free reg. The result is a memory leak from the original pointers that were in reg_store and a double-free on each element of reg_store when you try to clean everything up.
You need to copy reg into the memory already allocated in reg_store[count] (watching the size of course) or don't allocate any space for the elements of reg_store before the "in between" code at all.
The error was already pointed out so no need to write it again.
I can however point out that i don't like the way you are handling errors.
void freeRegStore(char** reg_store)
{
int i;
if (reg_store != NULL)
{
for (i = 0; i < 3; i++)
free(reg_store[i]);
free(reg_store);
}
}
char** allocRegStore()
{
int i;
char **reg_store;
reg_store = calloc(3 * (sizeof(char*)), 1);
if (reg_store != NULL)
{
for (i = 0; i < 3; i++)
{
reg_store[i] = malloc(2 * sizeof(char));
if (reg_store[i] == NULL)
{
freeRegStore(reg_store);
return NULL;
}
}
}
return reg_store;
}
In this method, the function allocRegStore will return NULL if there was not enough memory without leaving pieces around.
Then you can handle this case in main and not in the allocation function itself.
I disagree with the use of printf and exit inside functions.
int main()
{
char** reg_store = allocRegStore();
if (reg_store == NULL)
{
puts("Out of memory");
return 1;
}
... do your stuff
freeRegStore();
return 0;
}
I can also say that the memory used by this program will never go out of memory :) i would not worry about that.