I get a segmentation fault each time I'm trying to run this function.
char *hist_array[20];
int history_counter = 0;
void save_to_history(char *temp){
temp = malloc(512);/*512 is the size of temp array*/
printf("temp = %s\narray = %s",temp,hist_array[history_counter]);/*debug*/
strcpy(hist_array[history_counter],temp);
printf("Saved %s to history to %d\n\n",hist_array[history_counter],history_counter);
history_counter++;
}
I'm not sure whether I'm using malloc correctly or not, but as I understand it should help with properly saving my string temp to an array of strings hist_array. Also, temp is never NULL.
EDIT 1: Changed sizeof(temp) to its proper size 512, still getting segfault.
The problem is with the following statement -
strcpy(hist_array[history_counter], temp);
strcpy tries to copy the buffer pointed to by temp to the buffer pointed to by hist_array[history_counter] but char *hist_array[20]; defines hist_array to be an array of 20 pointers to characters. You should change your function to -
char *hist_array[20];
int history_counter = 0;
void save_to_history(char *temp) {
// +1 for the terminating null byte as strlen
// does not count the null byte
hist_array[history_counter] = malloc(1 + strlen(temp));
if(hist_array[history_counter] == NULL) {
printf("not enough memory to allocate\n");
// handle it
}
strcpy(hist_array[history_counter], temp);
printf("Saved %s to history to %d\n\n",
hist_array[history_counter],
history_counter);
history_counter++;
}
In your code, you are allocating via malloc but you don't initialize it. So when you do this:
printf("temp = %s\narray = %s",temp,hist_array[history_counter]);/*debug*/
strcpy(hist_array[history_counter],temp);
The should print some garbage and the subsequent strcpy will copy whatever is in temp at the time, until it encounters a 0 byte. You are invoking undefined behaviour here, because you should initialize the memory.
For example you could do:
memset(temp, 0, 512);
Additionally you are dereferencing pointers in your array hist_array. Since this is a global variable, all the pointers will originally be NULL pointers, which is causing your segfaul there.
Related
Curious about what is going wrong with this strcpy.
int main(void){
char *history[10];
for(int i = 0; i < 10; i++){
history[i] = NULL;
}
char line[80];
fgets(line,80,stdin);
strcpy(history[0],line); //This line segfaults
}
You've created an array of NULL pointers. You then tried to copy characters onto NULL. That's a no-no.
EDIT:
Your program could be optimized to this:
void main() {
char line[80];
fgets(line,80,stdin);
}
Your history array is never used to generate any output. So, while others have pointed out you need to allocate memory, technically, you could simply do this:
history[0] = line;
That will be a valid pointer up until the line goes out of scope, which is when history goes out of scope so it won't matter.
You need to allocate memory for history[0]. As history[0] is assigned NULL referencing it or writing to it will/may cause segfault.
something like
//this will create memory for 100 chars
history[0] = malloc(sizeof(char) * 100);
strcpy(history[0],line);
Or
//shortcut for both - this allocate new memory and returns pointer.
history[0] = strdup(line);
I am trying to compare two pointers which I have basically made into strings. I have no idea how to fix this but when I run it it gives me a seg fault at the strcmp.
Here's my code:
int find_next_string(int *position, char str[], char * mem_start, int mem_size)
{
int found = 0;
char *temp2;
int k = 0;
int i=(*position+1);
char *temp ;
int temp3 = 0;
temp = (char *) calloc(mem_size, sizeof(char));
temp2 = (char *) calloc(mem_size, sizeof(char));
temp3=*position;
while(i!=temp3 && found==0 && k==0){
//for(j=0;i<mem_size;i++){
temp2=mem_start;
// j++;
temp=strstr(temp2, str);
if(strcmp(temp2, temp)==0){
found=1;
k=i;
}
//}
if(i==mem_size)
i=0;
else
i++;
}
if(found)
print_line(k, mem_start, mem_size);
// 1. update the location to the first character matching str
// 2. print the 16-byte word containing the string and repeat
// printing words until all characters in str are displayed
// 3. set found to 1
// if not found, do not change location and do not print
free(temp);
free(temp2);
return found;
}
The crash is most likely not due to the strcmp calls, but due to the fact that you reassign temp2 and then try to free the new pointer. You do the same with temp.
If those new pointers are not allocated with malloc (or calloc which is essentially malloc plus memset) then you will have undefined behavior which is a very common cause of crashes. And regarding temp it can point to the middle of some memory, and attempting to call free on that pointer (even if it point into the middle of a chunk allocated with malloc) is also UB.
The free function must be passed a pointer returned by malloc, or NULL, nothing else.
This is a basic error:
temp=strstr(temp2, str);
if(strcmp(temp2, temp)==0){
If strstr does not find the string, then temp will be NULL. Passing NULL to strcmp causes undefined behaviour, and this could be the cause of the crash.
You need to check if ( temp == NULL ) and take some action, before calling strcmp.
I am trying to scan a bunch of characters into an array. I have used malloc to set the original size of the array, but I want to use realloc to increase the size if the user enters more characters than the initial size allows. I am not quite sure where to put the realloc, or if it should be within a conditional statement.
char *strscan(void) {
int size = sizeof(char) * 10;
char *a = malloc(size);
// Below I try to read character input from the user and store it in the array.
while (a != EOF) {
scanf("%c", a);
if (trace) printf("%c", *a);
++a;
a = realloc(a, 2 * size);
}
return a;
}
As of now I still get heap buffer overflow upon entering, for example, 15 characters.
++a;
a = realloc(a, 2 * size);
This is the problem. The first argument of realloc must be a pointer that is returned by the malloc family functions, or a null pointer. a used to be one, but by ++a;, it's not any more.
I see two problems here.
The first is that you're incrementing a, then passing the incremented value to realloc. Since the pointer passed to realloc was not a value returned from malloc, calloc, or realloc, or is NULL, this can cause errors.
The second problem is that you're not increasing the size of your memory buffer after the first call to realloc, since you're always passing it 2 * size and size never changes. So you eventually run past the end of the buffer.
You need a separate pointer to keep track of where the next character should go, and you need to keep track of how big your buffer currently is and realloc only when your existing buffer is almost full.
char *strscan(void) {
size_t size = sizeof(char) * 10;
char *a = malloc(size);
char *current; // The current character
ptrdiff_t diff;
current = a;
do {
scanf("%c", current);
if (trace) printf("%c", *current);
if (current - a >= size - 1) {
size *= 2;
diff = current - a;
a = realloc(a, size);
current = a + diff; // Since "a" could change, we need to modify "current" as well
}
} while (*current++ != '\n');
*current = '\x0';
return a;
}
Remove that ++a . It is the culprit here .
realloc() accepts the either the NULL pointer or the malloc returned pointer.
Read from the man page.
Hope you understand . Happy Coding..
You need two pointers. One is the location of the buffer. The other is the location of the current character. When the difference between them is large enough, reallocate the buffer and reset the pointers.
I am trying to write a basic CSV parser in C that generates a dynamic array of char* when given a char* and a separator character, such as a comma:
char **filldoc_parse_csv(char *toparse, char sepchar)
{
char **strings = NULL;
char *buffer = NULL;
int j = 0;
int k = 1;
for(int i=0; i < strlen(toparse); i++)
{
if(toparse[i] != sepchar)
{
buffer = realloc(buffer, sizeof(char)*k);
strcat(buffer, (const char*)toparse[i]);
k++;
}
else
{
strings = realloc(strings, sizeof(buffer)+1);
strings[j] = buffer;
free(buffer);
j++;
}
}
return strings;
}
However, when I call the function as in the manner below:
char **strings = filldoc_parse_csv("hello,how,are,you", ',');
I end up with a segmentation fault:
Program received signal SIGSEGV, Segmentation fault.
__strcat_sse2 () at ../sysdeps/x86_64/multiarch/../strcat.S:166
166 ../sysdeps/x86_64/multiarch/../strcat.S: No such file or directory.
(gdb) backtrace
#0 __strcat_sse2 () at ../sysdeps/x86_64/multiarch/../strcat.S:166
#1 0x000000000040072c in filldoc_parse_csv (toparse=0x400824 "hello,how,are,you", sepchar=44 ',') at filldocparse.c:20
#2 0x0000000000400674 in main () at parsetest.c:6
The problem is centered around allocating enough space for the buffer string. If I have to, I will make buffer a static array, however, I would like to use dynamic memory allocation for this purpose. How can I do it correctly?
Various problems
strcat(buffer, (const char*)toparse[i]); attempts to changes a char to a string.
strings = realloc(strings, sizeof(buffer)+1); reallocates the same amount of space. sizeof(buffer) is the size of the pointer buffer, not the size of memory it points to.
The calling function has no way to know how many entries in strings. Suggest andding a NULL sentinel.
Minor: better to use size_t rather than int. Use more descriptive names. Do not re-call strlen(toparse) repetitively. Use for(int i=0; toparse[i]; i++) . Make toparse a const char *
You have problems with your memory allocations. When you do e.g. sizeof(buffer) you will get the size of the pointer and not what it points to. That means you will in the first run allocate five bytes (on a 32-bit system), and the next time the function is called you will allocate five bytes again.
There are also many other problems, like you freeing the buffer pointer once you assigned the pointer to strings[j]. The problem with this is that the assignment only copies the pointer and not what it points to, so by freeing buffer you also free strings[j].
Both the above problems will lead to your program having undefined behavior, which is the most common cause of runtime-crashes.
You should also avoid assigning the result of realloc to the pointer you're trying to reallocate, because if realloc fails it will return NULL and you loose the original pointer causing a memory leak.
This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 3 years ago.
What is wrong with strcpy() in this code?
void process_filedata(char *filename)
{
void* content;
const char * buffer;
char * temp;
char * row;
char * col;
int lsize,buflen,tmp,num_scan; //num_scan - number of characters scanned
int m=0,p=0,d=0,j=0; //m - machine, p - phase, d- delimiter, j - job
FILE *file_pointer = fopen("machinetimesnew.csv","r");
if(file_pointer == NULL)
{
error_flag = print_error("Error opening file");
if(error_flag) exit(1);
}
fseek(file_pointer, 0 ,SEEK_END);
lsize = ftell(file_pointer);
buflen = lsize;
rewind(file_pointer);
// content = (char*) malloc(sizeof(char)*lsize);
fread(content,1,lsize,file_pointer);
buffer = (const char*) content;
strcpy(temp,buffer);
row = strtok(temp,"\n");
...............
...............
I am getting a segmentation fault..
You're not allocating any space for temp. It's a wild pointer.
There are actually three segmentation faults here:
fread(content,1,lsize,file_pointer);
strcpy(temp,buffer);
row = strtok(temp,"\n");
The first one is fread() which is attempting to write to memory that does not yet exist as far as your process is concerned.
The second one is strcpy(), (expounding on the first) you are attempting to copy to a pointer that points to nothing. No memory (other than the pointer reference itself) has been allocated for temp, statically or dynamically.
Fix this via changing temp to look like this (allocating it statically):
char temp[1024];
Or use malloc() to dynamically allocate memory for it (as well as your other pointers, so they actually point to something), likewise for content. If you know the needed buffer size at compile time, use static allocation. If not, use malloc(). 'Knowing' is the subject of another question.
The third one is strtok() , which is going to modify temp en situ (in place), which it obviously can not do, since temp was never allocated. In any event, don't expect temp to be the same once strtok() is done with it. By the name of the variable, I assume you know that.
Also, Initializing a pointer is not the same thing as allocating memory for it:
char *temp = NULL; // temp is initialized
char *temp = (char *) malloc(size); // temp is allocated if malloc returns agreeably, cast return to not break c++
Finally, please get in the habit of using strncpy() over strcpy(), its much safer.
Nothing's wrong with strcpy. You haven't initialised temp.
There's yet another mistake. fread does not add a nul character to the end of the buffer. That's because it only deals with arrays of bytes, not nul-terminated strings. So you need to do something like this:
content = malloc(lsize + 1);
fread(content,1,lsize,file_pointer);
content[lsize] = 0;
temp = malloc(lsize + 1);
strcpy(temp, content);
or this:
content = malloc(lsize);
fread(content,1,lsize,file_pointer);
temp = malloc(lsize + 1);
memcpy(temp, content, lsize);
temp[lsize] = 0;
(Also, in real code you should check the results of fread and malloc.)
you didn't allocate memory for temp
char * temp hasn't been initialized and you consequently haven't allocated any memory for it.
try:
temp = (char *)malloc(SIZE);
where SIZE is however much memory you want to allocate for temp
This piece of code intrigues me:
if(file_pointer == NULL)
{
error_flag = print_error("Error opening file");
if(error_flag) exit(1);
}
Shouldn't you exit unconditionally if the file_pointer is NULL?