This question already has answers here:
Facing an error "*** glibc detected *** free(): invalid next size (fast)"
(2 answers)
Closed 8 years ago.
Please help, I'm so new in C that I don't understand the problem
I have 3 files
main.c, set.c, set.h
in set.h
typedef struct Set{unsigned char array[16];
}Set;
in main.c
main method
int main
{
int i=0;
char *input="read_set A,0,1,2,3,4";
char *output[LEN_ACTIONS];
char *d=" ";
read_input(input, output, d,0);
char *methodName = output[0];
printf("method name:%s\n", methodName);
invoke_method(methodName, output);
for(i=0; i < LEN_ACTIONS; i++)
free(output[i]);
return 0;
}
in set.c
void read_input(char *input,char **output, char *delimiter, int onlyNumbers)
{
int index =0;
char *str =(char*)malloc(strlen(input));
strcpy(str, input);
char *tok=NULL;
tok = strtok(str,delimiter);
while(tok!=NULL)
{
char *dup = (char*)malloc(strlen(tok)+1);
if(dup)
{
if(onlyNumbers >0)
{
if(is_number(tok))
{
output[index] = strcpy(dup, tok);
index++;
}
}
else
{
output[index] = strcpy(dup, tok);
index++;
}
}
tok = strtok(NULL, delimiter);
}
free(str);
}
in main.c
void invoke_method(char *methodName, char **output)
{
int i=0;
char *d=",";
char *groups[5];
read_input(output[1], groups, d, 0);
if(strcmp(methodName,"read_set") ==0)
{
printf("group: %s\n", groups[0]);
d=",";
char *numbers[MAX_IN_SET]={NULL};
read_input(output[1], numbers, d, 1);
if(strcmp(groups[0], "A")==0)
{
printf("init A set\n");
initialize_set(&A); //initialize the array with 0
printf("input to set\n");
read_set(&A, numbers);
}
if(strcmp(groups[0], "B")==0)
{
initialize_set(&B);
read_set(&B, numbers);
}
if(strcmp(groups[0], "C")==0)
{
initialize_set(&C);
read_set(&C, numbers);
}
if(strcmp(groups[0], "D")==0)
{
initialize_set(&D);
read_set(&D, numbers);
}
if(strcmp(groups[0], "E")==0)
{
initialize_set(&E);
read_set(&E, numbers);
}
}
for(i=0; i<5; i++)
free(groups[i]);
}
in set.c
void read_set(struct Set *set, char **numbers)
{
int i=0;
for(i=0; i<MAX_IN_SET; i++)
{
if(numbers[i] != NULL && numbers[i] != '\0')
{
int number = atoi(numbers[i]);
int charIndex = number/8;
int bitIndex = number %8;
int bitPlace = 1<<(7-bitIndex);
unsigned char c = (unsigned char)bitPlace;
int numberExists = c & set->array[charIndex];
if(!numberExists)
{
set->array[charIndex] = c|set->array[charIndex];
/*printf("number %d has been added\n", number);*/
}
}
}
}
in terminal after I run this I get an error
* glibc detected* ./mainprog: free(): invalid next size (fast)
Thank you very much
At least one problem there:
char *str =(char*)malloc(strlen(input));
should be
char *str =(char*)malloc(strlen(input) + 1);
or better yet
char *str = strdup(input);
You're not allocating space for terminating 0, so following strcopy steps on the heap data structures.
Use valgrind to find more problems, if any.
A possible problem is the loop that frees the array of char*. One of them is:
for(i=0; i < LEN_ACTIONS; i++)
free(output[i]);
It depends on the input, but if there are not LEN_ACTIONS entries allocated in that array, then the free call is likely invalid because the array was not initialized to zeros (null). One possibility might be to initialize the array up front (because passing NULL to free is valid). Use something like this prior to its use:
memset(output, 0, sizeof(output));
The same potential problem exists with groups inside invoke_method.
Related
This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 12 days ago.
I am trying to make an array of modifiable length, i defined a function called "add" that should add a char to the last of the array, but this result in putchar and printf not working. Why is this happening? and how can i fix it?
the output should be "hix", and the output is apparently ""
#include <stdio.h>
typedef struct
{
char* ptr;
size_t len;
}
bytes;
void add(bytes text, char chr)
{
text.ptr[text.len++] = chr;
}
bytes parse(char text[])
{
size_t index = 0;
while (text[index]) ++index;
return (bytes) {text, index};
}
void print(bytes text)
{
for (size_t index = 0; index < text.len; ++index)
{
putchar(text.ptr[index]);
}
}
int main()
{
bytes str = parse("hi");
add(str, 'x'); // if i remove this line "print" works, but only prints "hi"
print(str);
return 0;
}
When you try to modify string literal you will get memory overflow allocation problem.
So Your final code with allocation memory to sort the problem of Segmentation fault (core dumped)
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char * ptr;
size_t len;
}
bytes;
void add(bytes * text, char chr) {
text -> ptr[text -> len++] = chr;
}
bytes parse(char text[]) {
size_t index = 0;
char * new_ptr = NULL;
while (text[index]) ++index;
new_ptr = (char * ) malloc(index + 1);
if (new_ptr == NULL) {
printf("Memory allocation failed!\n");
exit(1);
}
for (int i = 0; i < index; i++) {
new_ptr[i] = text[i];
}
new_ptr[index] = '\0';
return (bytes) {
new_ptr,
index
};
}
void print(bytes text) {
for (size_t index = 0; index < text.len; ++index) {
putchar(text.ptr[index]);
}
}
int main() {
bytes str = parse("hi");
add( & str, 'x');
print(str);
free(str.ptr);
return 0;
}
Result :
hix
You can check by compile this code on C compiler
This question already has answers here:
Why is this string reversal C code causing a segmentation fault? [duplicate]
(8 answers)
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 2 years ago.
int length(char *);
char* reverse(char *);
int main()
{
int a;
char p;
a=length("Computer");
printf("%d", a);
printf("\nReverse : %s", reverse("Computer"));
getch();
return 0;
}
int length(char *p)
{
int i;
for(i=0;*(p+i)!='\0'; i++);
return(i);
}
char* reverse(char *p)
{
int len, i;
char temp;
for(len=0; *(p+len)!='\0'; len++);
for(i=0; i<len/2; i++)
{
temp=*(p+i);
*(p+i)=*(p+len-1-i);
*(p+len-1-i)=temp;
}
return(p);
}
I am trying to print the length of the string inputted without using strlen() function and also creating a user defined function using pointer and function to reverse a string without using strrev() function. After compilation the program doesn't throws an error but it just does not display anything. The length is being printed correctly but the reverse section is not being printed and I can't figure out why? Help me out here people.
first of all, as user3121023 said, string constants (or literals) cannot be modified.
The problem was with indexes, pointer and at the end the piece of code that reverse the string. I adjust it in certain points and I'm gonna attach you here:
#include <stdio.h>
#include <stdlib.h>
int length(char *);
char * reverseWithDynamicMemory(char *, int);
char * reverseWithoutDynamicMemory(char *, int, char *);
int main() {
char *pWord = "Computer";
int wordLength = length(pWord);
char reverseWordWithouDynamicMemory[wordLength];
printf("Word Lenght: %d\n", wordLength);
printf("\nReverse with Dynamic Memory: %s\n", reverseWithDynamicMemory(pWord, wordLength));
printf("Reverse without Dynamic Memory: %s\n\n", reverseWithoutDynamicMemory(pWord, wordLength, reverseWordWithouDynamicMemory));
return 0;
}
int length(char *pWord) {
int i;
for (i = 0; *(pWord + i) != '\0'; i++);
return i;
}
char * reverseWithDynamicMemory(char *pWord, int length) {
int i = 0, end = length - 1;
char *reverseWord = (char *) malloc(sizeof(char) * length);
if(!reverseWord) {
printf("\nError allocating memory for reverseWord...\n");
exit(EXIT_FAILURE);
}
while (i < end || end >= 0) {
reverseWord[i] = pWord[end];
end--;
i++;
}
reverseWord[length] = '\0';
return reverseWord;
}
char * reverseWithoutDynamicMemory(char *pWord, int length, char *reverseWord) {
int i = 0, end = length - 1;
while (i < end || end >= 0) {
reverseWord[i] = pWord[end];
end--;
i++;
}
reverseWord[length] = '\0';
return reverseWord;
}
Some useful tips:
There was an implicit declaration of function 'getch' which is invalid in C99
Unused variable 'p'
Use more descriptive names
I've created a variable with dynamic memory inside the function reverse. Otherwise address of stack memory associated with local variable 'reverseWord' is returned.
Best regards,
Denny
The problem I want to solve is: Count the number of occurrences of key words in a C code. Here's the code:
The problem is that I get a segmentation fault. In my code I mentioned where
is the problem. Can you, please, explain me why ?
In header:
struct Chei
{
char *cuv;
int contor;
};
typedef struct Chei chei;
int ReadCode(char *a[]);
void determine(chei *Ch, char *temp, int size);
void Frequency(chei *Ch, int nr_lines, char *a[], int size);
In main:
chei tab_chei[] = {{"while", 0},{"if", 0}, {"case", 0}, {"switch", 0}};
int size = sizeof(tab_chei)/sizeof(tab_chei[0]);
char *Code[MaxL];
int nr_lines;
nr_lines = ReadCode(Code);//number of lines of text
Frequency(tab_chei, nr_lines, Code, size);
In function file:
I think there is no problem with reading text (function ReadCode() -- here I allocated memory for each Code[i] using malloc). I used an array of pointers to char for this.
// This functions determines if the word "temp" is a keyword, and increases
//"contor" if it is.
void determine(chei *Ch, char *temp, int size)
{
int i;
for (i = 0; i < size; ++i)
{
if (!strcmp(Ch[i].cuv, temp))
{
Ch[i].contor++;
break;
}
}
}
Array "a" contains the text.
void Frequency(chei *Ch, int nr_lines, char *a[], int size)
{
int i;
char temp[MaxCh];
char *token = 0;
strcpy(temp, a[0]);//I put a[0] as a particular case
token = strtok(temp, " ");
determine(Ch, token, size);
while (token != NULL)
{
token = strtok(NULL, " ");
determine(ch, token, size); //here is the problem.
//I observed that if I delete this line, there is no error
//but still it isn't what I want to get
}
for (i = 0; i < size; ++i)
{
printf("\n%-10s%-4d", Ch[i].cuv, Ch[i].contor);
}
}
token = strtok(NULL, " ");
determine(ch, token, size); //here is the problem.
You're not checking token before passing it to determine(). The strcmp() call is undefined behaviour when given a null pointer.
I think the problem is that you did not allocate memory for each of the string the pointer will point to, char *Code[MaxL];.
you only allocated memory for the pointers, you need to do something like
Code[0] = calloc(0, 100);
.
Please have a look at the following code:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
const char * cmd;
const char * help;
} CmdEnum;
static CmdEnum cmd_enum[] = {
{"help", "This help..."},
{"first", "The first command"},
{"second", "The second command"},
};
void main()
{
int i,n;
char *out = "";
n = sizeof(cmd_enum) / sizeof(CmdEnum);
for (i=0; i<n; i++)
{
char *oldOut = out;
CmdEnum cmd = cmd_enum[i];
asprintf(&out, "%s%s -> %s\n", oldOut, cmd.cmd, cmd.help);
if(i>0) free(oldOut);
}
printf("%s", out);
printf("Done.\n");
}
Is this a good way to build a text from the CmdEnum?
Is there a "nicer" way do define cmd in the first place as to avoid the if(i>0) free...?
Or am I doing something entirely wrong?
EDIT:
After reading larsmans' answer I modified main to:
int main()
{
int i,n, copied, siz;
char *out, *cursor;
siz = 1;// 1 for NUL char
n = sizeof(cmd_enum) / sizeof(CmdEnum);
for (i=0; i<n; i++)
{
siz += strlen(cmd_enum[i].cmd) + strlen(cmd_enum[i].help) + strlen(":\n\t\n\n");
}
out = malloc(siz);
if(!out)
{
printf("Could not alloc!\n");
return 1;
}
cursor = out;
for (i=0; i<n; i++)
{
copied = snprintf(cursor, siz, "%s:\n\t%s\n\n", cmd_enum[i].cmd, cmd_enum[i].help);
if(copied < 0 || copied >= siz)
{
printf("snprintf failed: %i chars copied.\n", copied);
return 1;
}
cursor += copied;
siz -= copied;
}
printf("%s", out);
printf("Done.\n");
free(out);
return 0;
}
(Note: I also changed the output format...)
Is this a good way to build a text from the CmdEnum?
Yes, except that asprintf is not portable (although you can define it easily in terms of snprintf for platforms that don't have it) and you're not checking error returns. void main isn't valid C btw.
Is there a "nicer" way do define cmd in the first place as to avoid the if(i>0) free...?
You could allocate the whole string beforehand.
size_t i, siz = 1; // 1 for NUL char
for (i=0; i<n; i++)
siz += strlen(cmd_enum[i].cmd) + strlen(cmd_enum[i].help) + strlen(" -> \n");
char *out = malloc(siz);
// check for errors
then build the string with snprintf. This saves you some malloc'ing and error checking in the loop.
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;
}