c stack variable corrupted - c

I have read all question for this type of problem but I can't fix mine.
The problem is that I use a function for reading data from a file and I get this error:
"Stack around variable 'p' was corrupted"
This is the function
Firm readFirm(char* name)
{
FILE* file = NULL;
int i = 0;
Firm firm;
char line[100];
char* p[5] = {(char*)malloc(50)};
char tmp[50];
strcpy(tmp,name);
strcat(tmp,".txt");
file = fopen(tmp,"rb");
getline(file,line,100);
strcpy(firm.name,line);
getline(file,line,100);
strcpy(firm.EIK,line);
getline(file,line,100);
split(p,line," ");
for (i = 0 ; p[i] != NULL; i++)
firm.price[i] = atoi(p[i]);
getline(file,line,100);
split(p,line,".");
firm.day = atoi(p[0]);
firm.month = atoi(p[1]);
firm.year = atoi(p[2]);
fclose(file);
return firm;
}
Please help because I don't know how to fix it!
This is the split function:
char ** split( char *result[], char *w, const char *delim)
{
int i=0;
char *p=NULL;
for(i=0, result[0]=NULL, p=strtok(w, delim); p!=NULL; p=strtok(NULL, delim), i++ )
{
result[i]=p;
result[i+1]=NULL;
}
return result;
}

The declaration char* p[5] = {(char*)malloc(50)}; has issues. It causes p[1], p[2], p[3], and p[4] to be initialized to garbage, most probably, not many would be NULL, which is what the loop tests for.
There are also problems with the use of getline(), most notably that the parameters are in the wrong order and not sufficiently indirected.

change the line:
char* p[5] = {(char*)malloc(50)};
to
char *p[5];
int i=0, n=5;
/* Allocate */
for (i=0; i<n; i++)
{
p[i] = malloc (sizeof (char) * 50);
}
/* Do work */
/* Deallocate */
for (i=0; i<n; i++)
{
free (p[i]);
}
EDIT1:
it looks like you wanted to achieve default assignment of the remaining locations like we can do with
char arr[10] = {0};
But in your case you have
char *p[5];
and for each location of p you need a separate memory location which needs to be individually assigned/allocated to and freed/deallocated from like above.
EDIT2:
In your split function you are doing a terrible thing. If you have allocated the memory for p in the main and then you pass it to the split function, then why are you assigning a pointer again into the p array elements. Each of the element of p points to an entire array (block of memory) which can be used to hold a string. So you should copy the part of the string into p[i] for some index i, with strcpy.
Also why are you returning the array? You have passed it as a pointer, and all the modifications you do to it in the function will persist after the return.
EDIT3:
Here is the modified split, made by applying minimum modifications to your code.
void split( char *result[], char *w, const char *delim)
{
int i=0;
char *p;
for(i=0, p=strtok(w, delim); p!=NULL; p=strtok(NULL, delim), i++ )
{
strcpy (result[i], p);
}
}
Here is a test main function:
int main (void)
{
char arr[128] = "10.08.1989";
char *p[5];
int i, n = 5;
for (i=0; i<n; i++)
{
p[i] = malloc (sizeof (char) * 50);
}
split (p, arr, ".");
printf ("%s\n", p[0]);
printf ("%s\n", p[1]);
printf ("%s\n", p[2]);
for (i=0; i<n; i++)
{
free (p[i]);
}
printf ("\n");
return 0;
}

Related

C program to do malloc and free on list of variable strings with char**

To allocate and free a single string in C, I do the following:
char[10] stringToCopy = "CopyString";
int length = strlen(stringToCopy) + 1;
char* CopiedString = malloc(length);
strcpy(CopiedString, stringToCopy, length);
printf("DatabasePath=%s\r\n", CopiedString);
free(CopiedString);
In my program, I need to copy such strings to a char** datatype. I need help in writing such a program. I am using a third party API which has a structure with this char** field entry.
I am not aware of how to allocate memory to this datatype and then copy the CopiedString into a list of such values. And also how to free the value after usage.
Allocating memory:
char **arr = malloc(r * sizeof(char *));
for (i=0; i<r; i++)
{
arr[i] = malloc(c * sizeof(char));
}
Freeing memory:
for (i=0; i<r; i++)
{
free(arr[i]);
}
free(arr);
I am not aware of how to allocate memory to this datatype ....
Follows is a useful C idiom for allocating.
size_t number_in_array = ...;
ptr = malloc(sizeof *ptr * number_in_array);
if (ptr == NULL) {
puts("Allocation failed");
} else {
puts("Success");
// Use ptr
free(ptr): // **
}
...
free(ptr): // **
// ** free(ptr) in 1 of 2 places.
Notice there is no need to code the type of the pointer in the allocation: ptr = malloc(sizeof *ptr * number_in_array);. This is easier to code right, review and maintain than attempting to code the type.
... then copy the CopiedString into a list of such values.
You already have good code to form a copied string. Make a helper function. Below is OP's with some improvements. Also research the common strdup() function.
char *my_strdup(const char *stringToCopy) {
size_t size = strlen(stringToCopy) + 1;
char* CopiedString = malloc(size);
if (CopiedString) {
memcpy(CopiedString, stringToCopy, size);
}
return CopiedString;
}
And also how to free the value after usage.
size_t number_in_array = 3;
char **ptr = malloc(sizeof *ptr * number_in_array);
if (ptr == NULL) {
puts("Allocation failed");
} else {
ptr[0] = my_strdup("Hello");
ptr[1] = my_strdup(" ");
ptr[2] = my_strdup("World");
// Use ptr (could check for ptr[] allocation failures first)
for (size_t i = 0; i < number_in_array; i++) {
free(ptr[i]);
}
free(ptr):
}
You can use strdup to create malloced string in c.
char ** presult = NULL;
for double pointer "presult" we can assign data like this.
if (presult) {
*presult = strdup("CopyString");
}
Sample code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int copy_data(char ** p) {
if (p) {
*p = strdup("Test data");
}
return 0;
}
int main () {
char * p = NULL;
copy_data(&p);
if (p) {
printf("daat : %s\n", p);
// free if not used
free(p);
p = NULL;
}
return 0;
}
Go through the below program which explains how to allocate memory for char** and also how to free the same.
Comments are in lined for understanding, please get back in case of any clarification needed.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define NUMBER_OF_STRINGS 5
#define MAX_LEN_OF_STRING 50
void printStrings_array(char ex_strings[][MAX_LEN_OF_STRING], int nstrings);
char** allocMemForStrings(int nStrings);
void printStrings_ptr(char** strings, int nStrings);
int main()
{
// example list of string for which we are going to allocate memory and store in char**
char ex_strings[NUMBER_OF_STRINGS][MAX_LEN_OF_STRING] =
{
"This is the First String",
"This is the Second String",
"This is the Third String",
"This is the Fourth String",
"This is the Fifth String",
};
printf("contents of char[][] \n");
printStrings_array(ex_strings, NUMBER_OF_STRINGS);
// list_of_strings is a variable which points to list of strings
char** list_of_strings = NULL;
// allocating memory for list of strings
if ( list_of_strings = allocMemForStrings(NUMBER_OF_STRINGS))
{
int i = 0;
printf("got %p for list_of_strings\n", (void*)list_of_strings);
while(i < NUMBER_OF_STRINGS)
{
size_t len = strlen(ex_strings[i])+1;
// allocate memory for each string as per its length
list_of_strings[i] = malloc(len);
printf("got %p for string %d\n", (void*)list_of_strings[i], i);
memset(list_of_strings[i], 0, len);
strncpy(list_of_strings[i], ex_strings[i], len);
i++;
}
printf("contents of char** \n");
printStrings_ptr(list_of_strings, NUMBER_OF_STRINGS);
// free ing the memory for char **
// first we need to free the memory for each of the strings pointed by the list_of_strings variable.
i = 0;
while(i < NUMBER_OF_STRINGS)
{
printf("\n freeing %p ", (void*)list_of_strings[i]);
free(list_of_strings[i]);
list_of_strings[i] = NULL;
i++;
}
//now free the list_of_strings pointer
printf("\n finally freeing %p ", (void*)list_of_strings);
free(list_of_strings);
// to avoid dangling pointers, its best practice to set the pointers = NULL after free.
list_of_strings = NULL;
}
else
{
printf("cannot allocate memory for strings\n");
}
return 0;
}
void printStrings_array(char ex_strings[][MAX_LEN_OF_STRING], int nstrings)
{
for(int i = 0; i< nstrings;i++)
printf(" %s\n", ex_strings[i]);
}
void printStrings_ptr(char** strings, int nStrings)
{
for(int i = 0; i< nStrings;i++)
printf(" %s\n", strings[i]);
}
char** allocMemForStrings(int nStrings)
{
// need to have memory to store nStrings
return malloc(nStrings * sizeof (char*));
}

How to pass array of char arrays to function by reference?

I want to initialize array of char arrays in a function:
void myFunction(char*** words)
{
int size = 3;
char** words_ = (char**) malloc(size * sizeof(char*));
for (int i=0; i< size; ++i)
{
// init each word words[i] with some value
}
*words = words_;
}
which I use in that way:
char** multiple_words;
myFunction(&multiple_words);
Is there any other way to write this code better/simpler?
(This code works BTW).
char** myFunction()
{
int size = 3;
char** words_ = (char**) malloc(size * sizeof(char*));
for (int i=0; i< size; ++i)
{
// init each word words[i] with some value
}
return words_;
}
char **words = myFunction();
You can simplify the malloc call itself a bit. You don't need to cast the result of malloc in C1, so that call could be simplified to
char** words_ = malloc(size * sizeof *words); // sizeof *words == sizeof (char *)
Always check the result of a malloc, calloc, or realloc call. Even though the likelihood of the request failing is small, it's not zero.
The words_ variable really serves no purpose, and at first glance looked like you were redeclaring the words function argument. It would be simpler to get rid of it entirely and just write
*words = malloc( sizeof **words * size ); // sizeof **words == sizeof (char *)
leaving us with
void myFunction(char*** words)
{
int size = 3;
*words = malloc(size * sizeof **words);
if ( *words )
{
for (int i=0; i< size; ++i)
{
// init each word words[i] with some value
}
}
}
At least as of the 1989 standard - if you're using an ancient K&R-era implementation or if you're compiling this code as C++, then a cast is required. However, if you're writing C++, then you shouldn't be using malloc anyway.
I would create abstractions depending on what I want to represent:
struct word {
char *letters;
};
struct sentence {
struct word *words;
};
// and then work with those abstractions:
int sentence_create(struct sentence *s) {
const size_t size = 3;
s->words = malloc(size * sizeof(*s->words));
if (s->words == NULL) goto ERR_WORDS;
s->words[0] = strdup("hello");
if (s->words[0] == NULL) goto ERR_0;
s->words[1] = strdup("world");
if (s->words[1] == NULL) goto ERR_1;
s->words[2] = NULL;
// success
return 0;
// goto error handling
free(s->words[1]);
ERR_1:
free(s->words[0]);
ERR_0:
free(s->words);
s->words = NULL;
ERR_WORDS:
return -ENOMEM;
}
int main() {
struct sentence sentence;
if (sentence_create(&sentence) != 0) {
fprintf(stderr, "Oh no!");
abort();
}
// TODO: sentence_destroy(&sentence) to free memory
}
Also see wiki.c2 Three Star Programmer
Not sure 100% whether it is easier or not:
typedef struct {
char **words;
} WordList;
void myFunc(WordList *wordList) {
...
wordList->words = malloc(numberOfWords * sizeof(char *));
// strSource : this string comes from somewhere in your code
...
for (int i = 0; i < numberOfWords; i++) {
int numberOfChars = strlen(strSource);
(wordList->words)[i] = malloc((numberOfChars + 1) * sizeof(char));
(wordList->words)[i][numberOfChars] = '\0';
...
strcpy((wordList->words)[i], strSource)
...
}
...
}
int main() {
WordList wordList;
...
myFunc(&wordList);
...
}
This is gonna get icky no matter how you write it.
A char** is fine to use for pointing at the first item in an array of char*, each pointing at a string of individual length.
It is best if the function can return a char**, but if that isn't possible, then...
We'd have to return a char** through parameters, means we have to write char***. Three levels of indirection is always questionable, but this specific case is about the only valid use for it. Or the lesser evil at least, since...
Some makeshift struct wrapper that does nothing but hiding away the *** isn't making the code any better or more readable. That's very similar to hiding pointers behind typedef, not recommended.
The least messy way to write that might be something like this:
void heard (char*** word, size_t size)
{
char** the_word = malloc( sizeof(char*[size]) );
for(size_t i=0; i<size; i++)
{
const char* str = "bird"; // some random data from somewhere
the_word[i] = malloc (sizeof str); // allocate room for individual strings
strcpy(the_word[i], str);
}
*word = the_word;
}
Then call it as:
char** word;
heard(&word, 3);
for(size_t i=0; i<3; i++)
{
puts(word[i]);
}
The most proper solution is probably to use a complete string container class which handles all of this for you. Then you'd just declare arrays of strings and don't worry about all the details of allocating things manually.

array value not updating

I have a strtok implementation (sort of), but it doesn't print the token!
char *tokenizer(char s[], const char *delimiter) {
char *p; //return value of function
int i = 0;
while(s[i] != *delimiter) //to get the size of array just right
i++;
char arr[i+1];
p = arr; //can't return an array, so assigned to a
//pointer
int j = 0;
i = 0;
while(s[i]!=*delimiter) {
arr[j] = s[i];
i++;
j++;
}
arr[j] = '\0';
printf("%s\n",p); //this statement works, but if excluded
//main prints nothing.
return p;
}
This function is being called as following, from the main:
char s[] = "tab-tab";
const char del[2] = "-";
char *p;
p = tokenizer(s, del);
printf("%s\n", p); //prints nothing without the printf in
//tokenizer
I tried debugging with gdb, and inspected the values of local variable after each line. p is updated with arr[j] inside tokenizer but goes to zero as soon as tokenizer finishes and frame shifts back to main.
The value ofp in main doesn't become NULL, it becomes an empty string, and prints that!
However, p in main prints the token if printf in tokenizer is included.
This already includes work-around. I know this can't possibly be the way strtok is implemented. I started with a more sophisticated, "expertish" version which had pointers, but couldn't get it to work, so settled for this "beginner" version.
It's because your pointer is pointing to a memory address in the stack, once your function is returned the memory address being pointed to no longer exists, you need to create dynamically allocated memory to access the variable outside of the function. The beauty of C
char *tokenizer(char s[], const char *delimiter) {
char *arr;
int i = 0;
while(s[i] != *delimiter)
i++;
// Initialize variable in the heap
if (!(arr = malloc(sizeof(char *) * (i+1))))
return NULL;
// Clear the array
bzero(arr, (i+1));
int j = 0;
i = 0;
while(s[i]!=*delimiter) {
arr[j] = s[i];
i++;
j++;
}
arr[j] = '\0';
// return pointer
return arr;
}
You should make sure to free the memory in the main to prevent memory leaks.

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 reference gone after for loop

i got a problem with my C code.
int split(char* source, char*** target, char* splitChar) {
int i;
int currentLength;
int splitCharPosition;
char* currentSubstring = source;
int splitCount = charcount(source, splitChar) + 1;
*target = (char**) malloc(splitCount * sizeof(char**));
for(i=0;i<splitCount;i++) {
splitCharPosition = indexOf(currentSubstring, splitChar);
substring(currentSubstring, target[i], 0, splitCharPosition);
currentLength = strlen(currentSubstring);
substring(currentSubstring, &currentSubstring, splitCharPosition + 1, curr entLength-splitCharPosition);
}
return splitCount;
}
The problem is that if I use the Debugger, the pointer to splitChar is set to 0x0 after the first run of the for loop.
Does anybody know why it is set to 0x0?
EDIT:
int indexOf(char* source, char* template) {
int i;
int j;
int index;
for (i = 0; source[i]; i++) {
index = i;
for (j = 0; template[j]; j++) {
if (source[i + j] != template[j]) {
index = -1;
break;
}
}
if (index != -1) {
return index;
}
}
return -1;
}
EDIT2:
int charcount(char* source, const char* countChar) {
int i;
int count = 0;
for(i=0;source[i];i++) {
if(source[i] == countChar[0]) {
count++;
}
}
return count;
}
EDIT3:
char* substring(char* source, char** target, int start, int length) {
*target = (char*) malloc(length + 1);
strncpy(*target, source + start, length);
target[length] = '\0';
return *target;
}
EDIT4:
I just noticed that if I add
char* sndfpgjps = splitChar;
to my split() code it does not delete the reference. Anyone know why?
This line:-
substring(currentSubstring, &currentSubstring, splitCharPosition + 1, curr entLength-splitCharPosition);
... will cause a memory leak, as well as being incredibly inefficient. The old substring is left dangling. and never freed.
It would be much better to write
currentSubString += splitCharPosition + 1;
I don't think that's the problem, but it's a problem.
Also, as you're using C library functions like strlen(), why aren't you using strtok or better yet, strtok_r?
I have some reservations about the code, but this works cleanly under valgrind (no leaks, no abuse). I've left the sub-functions largely unchanged except that constant strings are marked constant. The code in split() has been simplified. As I noted in a comment, I suggest writing the main split() function so that you have a local char **string_list; which you allocate and fill. Then, when you're about to return, you assign *target = string_list;. This will make it easier for you to understand what's going on. Triple indirection is nasty. You can justify it here (just), but minimize the time you spend working with triple pointers. The revision adopts that strategy.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int split(const char *source, char ***target, const char *splitStr);
static int
indexOf(const char *source, const char *template)
{
int i;
int j;
int index;
for (i = 0; source[i]; i++)
{
index = i;
for (j = 0; template[j]; j++)
{
if (source[i + j] != template[j])
{
index = -1;
break;
}
}
if (index != -1)
return index;
}
return -1;
}
static int
charcount(const char *source, const char *countChar)
{
int count = 0;
for (int i = 0; source[i]; i++)
{
if (source[i] == countChar[0])
count++;
}
return count;
}
static char *
substring(const char *source, int start, int length)
{
char *target = (char *)malloc(length + 1);
if (target != 0)
{
memmove(target, source + start, length);
target[length] = '\0';
}
return target;
}
int
split(const char *source, char ***target, const char *splitStr)
{
int splitCount = charcount(source, splitStr) + 1;
char **result = (char **)malloc(splitCount * sizeof(*result));
if (result == 0)
return -1;
int splitLength = strlen(splitStr);
char **next = result;
const char *currentSubstring = source;
for (int i = 0; i < splitCount; i++)
{
int splitCharPosition = indexOf(currentSubstring, splitStr);
if (splitCharPosition < 0)
break;
*next++ = substring(currentSubstring, 0, splitCharPosition);
currentSubstring += splitCharPosition + splitLength;
}
*next++ = substring(currentSubstring, 0, strlen(currentSubstring));
*target = result;
return (next - result); /* Actual number of strings */
}
static void print_list(int nstrings, char **strings)
{
for (int i = 0; i < nstrings; i++)
{
if (strings[i] != 0)
printf("%d: <<%s>>\n", i, strings[i]);
}
}
static void free_list(int nstrings, char **strings)
{
for (int i = 0; i < nstrings; i++)
free(strings[i]);
free(strings);
}
int main(void)
{
const char source[] = "This is a string; it is really!";
char **strings;
int nstrings;
nstrings = split(source, &strings, " ");
printf("Splitting: <<%s>> on <<%s>>\n", source, " ");
print_list(nstrings, strings);
free_list(nstrings, strings);
nstrings = split(source, &strings, "is");
printf("Splitting: <<%s>> on <<%s>>\n", source, "is");
print_list(nstrings, strings);
free_list(nstrings, strings);
return 0;
}
Note that in the second example, charcount() returns 6 but there are only 4 strings. This caused a late adjustment to the source code. (You could realloc() the result so it is exactly the right size, but it probably isn't worth worrying about unless the discrepancy is really marked — say 'more than 10 entries'.) The error handling is not perfect; it doesn't access invalid memory after failure to allocate, but it doesn't stop trying to allocate, either. Nor does it report failures to allocate individual strings — it does for failure to allocate the array of pointers.
I'd probably avoid the triple pointer by creating a structure:
typedef struct StringList
{
size_t nstrings;
char **strings;
} StringList;
You can then pass a pointer to one of these into split(), and into the utility functions such as free_list() and print_list(). The free_list() function would then modify the structure so that both elements are zeroed after the data pointed at by the structure is freed.
I'd also be tempted to use a different implementation of indexOf():
int indexOf(const char *haystack, const char *needle)
{
const char *pos = strstr(haystack, needle);
if (pos != 0)
return (pos - haystack);
return -1;
}
I do not know what substring does, nor what signature it has, but in the line
substring(currentSubstring, target[i], 0, splitCharPosition);
target[i] is only defined for i==0. I believe you wanted to write
substring(currentSubstring, (*target)[i], 0, splitCharPosition);
See if your debugger also supports data breakpoints, i.e. break if some place in memory is modified. Then place one at the actual address of splitChar, and another at the address it points to. (Since you didn't specify whether the pointer is null or points to nil.) See where it breaks. It may be that it is a completely unrelated place; that would indicate a buffer overflow.
Also, you could make at least splitChar a pointer to const. You don't actually want to modify it, right? Better idea, make it a char, not a pointer, since its name suggests that there is only one character on which you split, not a string.
The first call to substring does not look correct:
substring(currentSubstring, target[i], 0, splitCharPosition);
I suspect it should be something like the following where it indexes the actual memory that was allocated:
substring(currentSubstring, &((*target)[i]), 0, splitCharPosition);
You first need to get the value that target points at (*target) and then index off of that and pass the address of that array location.

Resources