Failing to assign memory to a pointer of a pointer - c

My problem is that it fails to assign memory to a (char*) pointer and I can't seem to understand why.
I reviewed other similar questions, but I can't seem to grasp the answer.
I'm trying to return a list of strings, but I know that in C I can't return char**, but I can do that via the char** parameter. My attempt is in the code snippets below.
in a.c
void list(char** fileList) {
int fileIndex = 0;
fileList = (char**)malloc(DIRECTORY_SIZE * sizeof(char*));
while ((dir = readdir(currentDirectory)) != NULL)
{
fileList[fileIndex] = (char*)malloc(FILENAME_LENGTH * sizeof(char)); //It fails here
fileList[fileIndex] = strncpy(fileList[fileIndex], dir->d_name, FILENAME_LENGTH);
fileIndex++;
printf("%s\n", fileList[fileIndex]);
}
}
in main.c
int main() {
char** fileList;
list(fileList);
for(int i = 0; i < 10; i++) {
printf("%s\n", fileList[i]);
}
}
I already looked over these questions:
Assigning memory to double pointer?
segment fault, assigning to double pointer in c
Assigning memory to double pointer?

What happens is that the memory pointer fileList gets copied to the list function, when the list function then changes the pointer, but the initial pointer wouldn't change.
To fix this you could give it a pointer to the pointer to change the actual pointer value, like this:
void list(char*** fileList) {
int fileIndex = 0;
*fileList = (char**)malloc(DIRECTORY_SIZE * sizeof(char*));
while ((dir = readdir(currentDirectory)) != NULL)
{
*fileList[fileIndex] = (char*)malloc(FILENAME_LENGTH * sizeof(char)); //It fails here
*fileList[fileIndex] = strncpy(fileList[fileIndex], dir->d_name, FILENAME_LENGTH);
fileIndex++;
printf("%s\n", fileList[fileIndex]);
}
}
int main() {
char** fileList;
list(&fileList);
for(int i = 0; i < 10; i++) {
printf("%s\n", fileList[i]);
}
}
But I personally find this a bit clunky, so it would be better to do it like this:
char** list(void) {
char** fileList;
int fileIndex = 0;
fileList = (char**)malloc(DIRECTORY_SIZE * sizeof(char*));
while ((dir = readdir(currentDirectory)) != NULL)
{
fileList[fileIndex] = (char*)malloc(FILENAME_LENGTH * sizeof(char)); //It fails here
fileList[fileIndex] = strncpy(fileList[fileIndex], dir->d_name, FILENAME_LENGTH);
fileIndex++;
printf("%s\n", fileList[fileIndex]);
}
return filelist;
}
int main() {
char** fileList = list();
for(int i = 0; i < 10; i++) {
printf("%s\n", fileList[i]);
}
}

Related

Using an array of structures with call by reference

Here is my problem: I have to make this program for school and I spent the last hour debugging and googling and haven't found an answer.
I have an array of structures in my main and I want to give that array to my function seteverythingup (by call by reference) because in this function a string I read from a file is split up, and I want to write it into the structure but I always get a SIGSEV error when strcpy with the struct array.
This is my main:
int main(int argc, char *argv[])
{
FILE* datei;
int size = 10;
int used = 0;
char line[1000];
struct raeume *arr = (raeume *) malloc(size * sizeof(raeume*));
if(arr == NULL){
return 0;
}
if(argc < 2){
return 0;
}
datei = fopen(argv[1], "rt");
if(datei == NULL){
return 0;
}
fgets(line,sizeof(line),datei);
while(fgets(line,sizeof(line),datei)){
int l = strlen(line);
if(line[l-1] == '\n'){
line[l-1] = '\0';
}
seteverythingup(&line,arr,size,&used);
}
ausgabeunsortiert(arr,size);
fclose(datei);
return 0;
}
and this is my function:
void seteverythingup(char line[],struct raeume *arr[], int size,int used)
{
char *token,raumnummer[5],klasse[6];
int tische = 0;
const char c[2] = ";";
int i=0;
token = strtok(line, c);
strcpy(raumnummer,token);
while(token != NULL )
{
token = strtok(NULL, c);
if(i==0){
strcpy(klasse,token);
}else if(i==1){
sscanf(token,"%d",&tische);
}
i++;
}
managesize(&arr[size],&size,used);
strcpy(arr[used]->number,raumnummer);
strcpy(arr[used]->klasse,klasse);
arr[used]->tische = tische;
used++;
}
Edit: Since there is more confusion I wrote a short program that works out the part you are having trouble with.
#include <cstdlib>
struct raeume {
int foo;
int bar;
};
void seteverythingup(struct raeume *arr, size_t len) {
for (size_t i = 0; i < len; ++i) {
arr[i].foo = 42;
arr[i].bar = 53;
}
}
int main() {
const size_t size = 10;
struct raeume *arr = (struct raeume*) malloc(size * sizeof(struct raeume));
seteverythingup(arr, size);
return 0;
}
So basically the signature of your functions is somewhat odd. Malloc returns you a pointer to a memory location. So you really dont need a pointer to an array. Just pass the function the pointer you got from malloc and the function will be able to manipulate that region.
Original Answer:
malloc(size * sizeof(raeume*));
This is probably the part of the code that gives you a hard time. sizeof returns the size of a type. You ask sizeof how many bytes a pointer to you raeume struct requires. what you probably wanted to do is ask for the size of the struct itself and allocate size times space for that. So the correct call to malloc would be:
malloc(size * sizeof(struct raeume));

C - Cant free char** pointer memory - error CrtIsValidHeapPointer

I have a function which builds an array of strings (char*) .
After I finished using the array I want to free its memory but then I get a CrtIsValidHeapPointer Error.
Code:
int main(int argc, char * argv[])
{
char** arr = NULL;
creating_array(&arr); // Building the array
//free each string memory
for (size_t i = 0; i < 4; i++)
{
free(arr[i]);
}
// until here everything works fine :)
//free the array memory
free(arr); // Error CrtIsValidHeapPointer
return 0;
}
void creating_array(char*** pArr)
{
char** arr = (char**)malloc(4);
arr[0] = (char*)malloc(5 * sizeof(char));
strcpy(arr[0], "aaaa");
arr[1] = (char*)malloc(5 * sizeof(char));
strcpy(arr[1], "bbbb");
arr[2] = (char*)malloc(5 * sizeof(char));
strcpy(arr[2], "cccc");
arr[3] = (char*)malloc(5 * sizeof(char));
strcpy(arr[3], "dddd");
*pArr = arr;
}
Why does it happen?
Please try, in creating_array
char **arr ;
arr=(char **) calloc( 4 , sizeof(char *));
Here is the working code. It compiles and runs now.
Generally after freeing a pointer, people set it to NULL to avoid confusion (so that any time a pointer is not null it points to valid memory). That avoids bugs. Also it is legal to free(NULL), so you don't get into very severe and hard-to- debug problems that happen if you double-free an address.
One important point, is that in this case, the parenthesis in this case (*pArr)[2] are important, to override the operator precedence in C. If you try *pArr[2] it assumes you mean to de-reference the pointer stored at element [2]. (*pArr)[2] means return element at element to from the the location at the address pointed to by pArr. The reason C assumes the other case and that you need parens in this case is that the other use is much much more common, so it is convenient.
Note: ALWAYS check return values for malloc() and function calls and have a strategy to catch and log errors. Otherwise as you start writing bigger programs you will find them extremely difficult, troublesome or nearly impossible to debug.
Another thing is to create named constants instead of literals, because then it is clear what the number is and how it is used, and if that number is needed in more than one place it can be changed in one place. It makes the program easier to read and understand.
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#define STRING_COUNT 4
char **create_array(char ***pArr);
int
main()
{
char **arr = NULL;
if (create_array(&arr) == NULL) {
fprintf(stderr, "out of memory - exiting\n");
return -1;
}
for (size_t i = 0; i < STRING_COUNT; i++) {
printf("%s\n", arr[i]);
}
for (size_t i = 0; i < STRING_COUNT; i++) {
free(arr[i]);
arr[i] = NULL;
}
free(arr);
return 0;
}
char **
create_array(char ***pArr)
{
if ((*pArr = malloc(STRING_COUNT * sizeof (char **))) == NULL) {
return NULL;
}
if (((*pArr)[0] = strdup("aaaa")) == NULL) {
return NULL;
}
if (((*pArr)[1] = strdup("bbbb")) == NULL) {
free((*pArr)[0]);
*pArr[0] = NULL;
return NULL;
}
if (((*pArr)[2] = strdup("bbbb")) == NULL) {
free((*pArr)[0]);
*pArr[0] = NULL;
free((*pArr)[1]);
*pArr[1] = NULL;
return NULL;
}
if (((*pArr)[3]= strdup("bbbb")) == NULL) {
free((*pArr)[0]);
*pArr[0] = NULL;
free((*pArr)[2]);
*pArr[1] = NULL;
free((*pArr)[2]);
*pArr[2] = NULL;
return NULL;
}
return *pArr;
}

Calling function in c will cause the string value in struct turn into garbage value

This code has a problem in the struct data members. When I call a function like Evaluator() function the token[0].value will corrupt or will turn into a garbage. I tried to allocate a memory for the value data member but still no luck. I also tried to allocate a memory for the struct itself but still it doesn't work. Can someone help me with this?
struct tokens
{
char *value;
char type = ' ';
};
void inputComponent(char input_string[size])
printf("\n> ");
scanf("%[^\n]s", input_string);
}
int processingComponent(char *input_string, int *result)
{
int error_flag = 0;
tokens token[size];
error_flag = Parser(input_string, token);
if (error_flag == 0)
error_flag = Evaluator(result, token);
return error_flag;
}
int Parser(char *input_string, struct tokens token[size])
{
char valid_operators[size] = { "+-*/%" };
char temp = ' ';
char number_string[size] = { NULL };
int counter = 0;
int countStruct = 0;
int tempCounter = 0;
do
{
temp = input_string[counter];
if (isdigit(temp))
{
number_string[tempCounter] = temp;
tempCounter++;
}
else if (strpbrk(input_string, valid_operators))
{
if (temp == '%')
return (-1);
else if (number_string != NULL)
{
char tempNum[size] = { NULL };
strcpy(tempNum, number_string);
token[countStruct].value = tempNum;
token[countStruct].type = 'N';
countStruct++;
tempCounter = 0;
for (int x = 0; number_string[x] != NULL; x++)
number_string[x] = NULL;
}
}
else
return (-2);
counter++;
} while (counter < strlen(input_string));
return 0;
}
int Evaluator(int *result, struct tokens token[size])
{
for(int x = 0; x < 3; x++) //value of token[0].value = ÌÌÌÌÌÌÌÌÌÌÌÌ
printf("%s", token[x].value);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
char input_string[size] = { NULL };
int result = 0;
int error_flag = 0;
inputComponent(input_string);
error_flag = processingComponent(input_string, &result);
_getch();
_getch();
return 0;
}
For starters, when you pass an array of tokens to the Parser and Evaluator functions, you are passing the variables by value. The token array is not actually changed after calling Parser():
`
int Parser(char *input_string, struct tokens myArray[size])
{
//modifying myArray will not modify the array that was actually passed
//to this function from the processingComponent() function.
}
`
First change your Parser and Evaluator functions like so:
#define ARRAY_SIZE 100 //an arbitrary size
int Parser( char* input_string, struct token* tokenArray )
{
//access each element as so:
//tokenArray[0];
//tokenArray[ ARRAY_SIZE - 1 ];
}
int Evaluator(int *result, struct token* tokenArray )
{
for(int x = 0; x < ARRAY_SIZE; x++)
printf("%s", tokenArray[x].value);
return 0;
}
Then call the Parser() function as so:
EDIT: Since it is a good idea to allocate and free memory within the same function (so that you don't end up with spaghetti code), this would be a better solution:
int processingComponent(char *input_string, int *result)
{
int error_flag = 0;
token tokenArray[ARRAY_SIZE];
//allocate memory here
for( int i = 0; i < ARRAY_SIZE; i++ ) {
tokenArray[i].value = (char*)malloc( sizeof(char) * MAX_STRING_LENGTH);
}
error_flag = Parser(input_string, &tokenArray[0]);
if (error_flag == 0)
error_flag = Evaluator(result, &tokenArray[0]);
//free memory here before the token array goes out of scope:
for( int i = 0; i < ARRAY_SIZE; i++ ) {
free( tokenArray[i].value );
tokenArray[i].value = NULL;
}
return error_flag;
}
When you allocate memory for your token string, it needs to be dynamically allocated using malloc() and deleted using free().
Replace this:
strcpy(tempNum, number_string);
token[countStruct].value = tempNum;
//with:
#define MAX_STRING_LENGTH 255 //arbitrary
//Memory has already been allocated, so just copy the string into the token
strncpy( token[countStruct].value, number_string, MAX_STRING_LENGTH - 1 );
token[countStruct].value[MAX_STRING_LENGTH-1] = NULL;
You don't appear to be allocating any storage for token[].value. You set it equal to tempNum, but that goes out of scope in the inner block in Parser(). I would say that anything this code does is undefined because you're accessing memory that was deallocated when Parser() returned.
Precautions with Structures
I have added a text file, which contains your running code with instructions.
one important thing you can not assign any thing directly into structure, because declaration of structure reserve no space.
Why did you do such a hectic job to achieve something like this..
input :12+3-1/7
output:12317
Click this link to get your running c code

Can't pass char*** as argument

It's easy to see what am trying to accomplish here. read the list of files and pass it to another function.
Why this doesn't work.
when i try to store the filenames in a local char**, it works just fine, but can't send it back via the pointer. Gives segmentation fault.
int main(){
char** fileList;
int noOfFiles;
char* path = ".";
makeList(&fileList, &noOfFiles, path);
return 0;
}
void makeList(char ***fileList, int* noOfFiles, char* path){
struct dirent **fileListTemp;
*noOfFiles = scandir(path, &fileListTemp, NULL, alphasort);
int i;
fileList = malloc(sizeof(char***));
*fileList = malloc(sizeof(char**));
printf("total: %d files",*noOfFiles);
for(i = 0; i < *noOfFiles; i++){
printf("%s\n",fileListTemp[i] -> d_name); //works just fine
}
*fileList = malloc(*noOfFiles * sizeof(char*));
for(i=0; i < *noOfFiles; i++){
//*fileList[i] = fileListTemp[i] -> d_name; this didn't work either...
strcpy(*fileList[i], fileListTemp[i]->d_name);
printf("%s\n", *fileList[i]);
}
//fileList = &list;
return;
}
segmentation fault always...
and no hope of printing the fileList from main()
Here you overwrite the pointer to your char** fileList, which might be one problem:
fileList = malloc(sizeof(char***));
Here you overwrite a previously allocated pointer, which looks like another problem:
*fileList = malloc(*noOfFiles * sizeof(char*));

add_to_array call results in NULL list

I have a C struct that basically contains two 2D char arrays called List. One for appended items and another for inserted items. Then use external functions that add C strings to these arrays called add_to_array.
The problem I'm having is when I call add_to_array once it goes through without issues but once called a second time, I get a segmentation fault. With test code, I discovered for what ever reason that I can't figure out, the 2D array(s) in List remain NULL after calling add_to_array. I checked the result of add_to_array and it returns 1 (success) every time.
the target system/OS is Ubuntu linux.
typedef struct
{
char** appended;
char** inserted;
size_t app_alloc;
size_t app_elem;
size_t ins_alloc;
size_t ins_elem;
}
List;
void init_list(List* list)
{
list->app_alloc = 0;
list->ins_alloc = 0;
list->app_elem = 0;
list->ins_elem = 0;
list->appended = NULL;
list->inserted = NULL;
}
void free_list(List* list)
{
size_t i = 0;
for (; i < list->ins_elem; ++i)
{
free(list->inserted[i]);
}
free(list->inserted);
i = 0;
for (; i < list->app_elem; ++i)
{
free(list->appended[i]);
}
free(list->appended);
}
int add_to_array(const char* in, char** array, size_t* alloc, size_t* elem)
{
if (*alloc == *elem)
{
if (*alloc == 0) *alloc = list_buff;
else *alloc = (*alloc) * 2;
char** _tmp = (char**) realloc(array, (*alloc) * sizeof(char*));
if (!_tmp) return 0;
else array = _tmp;
}
array[(*elem)] = (char*) malloc(strlen(in) + 1);
strcpy(array[(*elem)], in);
(*elem)++;
return 1;
}
int append_list(const char* in, List* out)
{
return add_to_array(in, out->appended, &out->app_alloc, &out->app_elem);
}
int insert_list(const char* in, List* out)
{
return add_to_array(in, out->inserted, &out->ins_alloc, &out->ins_elem);
}
int main()
{
List test;
init_list(&test);
append_list("test", &test);
if (!test.appended)
{
printf("*%s*", "why is test.appended still NULL?");
}
//append_list("wwww", &test);
//insert_list("ffff", &test);
//printf("%s\n", get_element(0, &test));
//printf("%s\n", get_element(1, &test));
//printf("%s\n", get_element(2, &test));
//free_list(&test);
return 0;
}
Output: why is test.appended still NULL?
thanks to David's advice, I got my code working here's the changes:
int add_to_array(const char* in, char*** array, size_t* alloc, size_t* elem)
{
if (*alloc == *elem)
{
if (*alloc == 0) *alloc = list_buff;
else *alloc = (*alloc) * 2;
char** _tmp = (char**) realloc((*array), (*alloc) * sizeof(char*));
if (!_tmp) return 0;
else (*array) = _tmp;
}
(*array)[(*elem)] = (char*) malloc(strlen(in) + 1);
strcpy((*array)[(*elem)], in);
(*elem)++;
return 1;
}
int append_list(const char* in, List* out)
{
return add_to_array(in, &out->appended, &out->app_alloc, &out->app_elem);
}
int insert_list(const char* in, List* out)
{
return add_to_array(in, &out->inserted, &out->ins_alloc, &out->ins_elem);
}
Because C is a pass-by-value language :-)
You seem to be expecting that when you call:
add_to_array(in, out->appended, &out->app_alloc, &out->app_elem);
and then do
int add_to_array(const char* in, char** array, size_t* alloc, size_t* elem)
{
....
array = _tmp;
....
that the change to array will also change out->appended.
If you want it to work that way, you would have to pass a pointer to out->appended, and make add_to_array look like
int add_to_array(const char* in, char*** array, size_t* alloc, size_t* elem)

Resources