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);
.
Related
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));
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.
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, ¤tSubstring, 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, ¤tSubstring, 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.
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;
}
int main() {
Employee *array[SIZE]; //Employee is a typedef struct --includes char *name, DATE *dateOfBirth, DATE is also a typedef struct, has 3 int fields month, day, year,`
fillArray(array, &count, fpin1, fpin2);
freeMemory(array, int count);
}
fillArray(Employee *array[], int *count, FILE *fpin1, FILE *fpin2)
char buffer[MAX], buffer2[MAX];
while (fgets(buffer, MAX, fpin1) != NULL && fgets(buffer2, MAX, fpin2) != NULL){
array[*count]->name = (char *) malloc(sizeof(char)*25);
assert(array[*count]->name != NULL);
strncpy(array[*count]->name, buffer, 15);
strncpy(buffer2, temp, 2);
array[*count]->dateOfBirth->day = atoi(temp)
}
The code compiles but keeps failing with segmentation fault, it seems to fail at my fgets? or my malloc, what am I doing wrong? I really can't seem to figure that out.
Also how would you go about freeing this memory in a
freeMemory(Employee *array[], int count)
function?
Should be:
int main() {
Employee array[SIZE]; //Employee is a typedef struct --includes char *name, DATE *dateOfBirth, DATE is also a typedef struct, has 3 int fields month, day, year,`
fillArray(&array, &count, fpin1, fpin2);
freeMemory(&array, int count);
}
You aren't allocating your Employee objects anywhere, so array[0] points to some random address.
Employee* array[SIZE];
This is an array that stores pointers to Employee structs.
I think you mean
fillArray(Employee* array[], int* count, FILE *fpin1, FILE *fpin2)
{
char buffer[MAX], buffer2[MAX];
int i = 0;
while ( fgets(buffer, MAX, fpin1) != NULL &&
fgets(buffer2, MAX, fpin2) != NULL )
{
// the array does not hold any valid memory address.
array[i] = malloc( sizeof(Employee) );
assert( array[i] != NULL );
// now on the new employee add some char memory
(array[i])->name = malloc( sizeof(char) * 25 );
assert(array[i]->name != NULL);
strncpy(array[i]->name, buffer, 15);
strncpy(buffer2, temp, 2);
array[i]->dateOfBirth->day = atoi(temp)
++i;
(*count)++;
}
}
doing array[*count] besides looking weird, always modifies the same index. You never modified *count anywhere.
This code does not check that you do not exceed the bounds of the array passed.
Also : for the freeMemory()
freeMemory(Employee* array[], int count)
{
int i = 0;
while( i < count )
{
free(array[i]);
array[i] = NULL;
++i;
}
}