Below is the code for a method i made called inputReader it reads input from a textfile and copies it to a struct wordz and from that struct i retrieve the 3 most frequent words which is what is displayed below.
I am trying to concatenate all 3 words as one pointer so i can return it to the main method but whenever i use any method to do with w1, w2, w3, that copies to a new struct or array or pointer i ALWAYS get this error "Segmentation fault(core dumped)"
Any idea why this happens or how I can work around it?
Struct Code:
#define maxLetters 101
typedef struct {
char word[maxLetters];
int freq;
} WordArray; //struct type
Code:
char * w1; // most frequent word
char * w2; // second most frequent word
char * w3; // third most frequent word
// finds w1
for(j = 0; j < uniqueWords; j++)
if(wordz[j].freq == freqz[uniqueWords-2]+1)//excludes whitespace frequency
w1 = wordz[j].word;
// finds w2
for(j = 0; j < uniqueWords; j++)
if(wordz[j].freq == freqz[uniqueWords-3]+1)//excludes whitespace frequency
w2 = wordz[j].word;
// finds w3
for(j = 0; j < uniqueWords; j++)
if(wordz[j].freq == freqz[uniqueWords-4]+1)//excludes whitespace frequency
w3 = wordz[j].word;
char *p;
// if i dont include strcat methods the method runs fine and outputs fine
strcat(p, w1); // once this operation is executed i get the error
strcat(p, " ");
strcat(p, w2);
strcat(p, " ");
strcat(p, w3);
You're trying to concatenate to an uninitialized pointer. Allocate memory to 'p'.
char *p = malloc(size)
It's a good idea to read the documentation of strcat thoroughly to check you are using it properly. You can look here http://man7.org/linux/man-pages/man3/strcat.3.html for example. There are also plenty of answers to similar questions on stackoverflow that you would have found helpful:
Segmentation fault- strcat
strcat causing segmentation fault
strcat segmentation fault
However, to save you some anguish, the fault is because to have not allocated any space for the results string p. strcat does not do this in C like it might in C# or other languages.
You would need:
char p[maxletters];
Better still, you should use strncpy with the size limit to prevent memory corruption:
strncpy(p, w1, maxletters);
The root cause leading to your issue is that p does not point anywhere, so trying to copy data to it invokes the infamous Undefined Behaviour.
So allocate some memory to p, either from the heap or from the stack.
To get it from the heap do:
char * p = malloc(some_size);
When then trying to strcat() data to this pointer be aware that strcat() expects its 1st argument to already point to a valid C-"string", that is a 0-teminated char array, to that it can concatenate what the 2nd argument is pointing to.
To take care this, make sure the data p is pointing to is does at least has its first bytes set to 0:
p[0] = '\0';
if not all bytes:
memset(p, 0, some_size);
If going for the latter you might also like to do:
char * p = calloc(some_size, sizeof *p);
As calloc() does the same as malloc() and addtionally initilaises all memory allocated with 0s.
If you feel initalising is to much effort then you cannot start concatenating using strcat(), but nered to start with strcpy() which does not rely on its 1st argument pointing to a valid C-"string", but simply copies what its 2nd argument is pointing to to where its 1st argement is pointing to.
chart * p = malloc(some_size);
strcpy(p, w1);
strcat(p, " ");
...
Finally:
Do not forget to call free() on p if the memory isn't needed anymore, to avoids a memory leak.
Also always check the outcome of memory allocation, that is check the result of malloc/calloc() against NULL, before using it.
Related
I'm required to save data, which happens to be a char array of 4096 characters tops, in a specified memory address.
So here i get the memory address from a uint32_t into the void* ptrAddress
uint32_t number = 1268;
void* ptrAddress = &number;
and here i try to copy the array of As, which works! but not really, because i get some garbage in the middle
char tryArray[4096];
for(int i = 0; i < 4095; i++ ){
tryArray[i] = 'A';
}
//EDIT: added the null terminator (forgot to do that)
tryArray[4095] = '\0';
char* copy = strcpy(ptrAddress, (char*)tryArray);
printf("lets see: %s\n", copy);
output (imagine 4096 As and 'garbage' as some garbage character):
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'garbage''garbage''garbage'AAAAAAAAAAAAAAAAA
And after that i get a seg fault
What am i doing wrong? If there's anything more you need to know from the code or my intentions with it, please tell me!
You have a couple of problems.
First, this code:
uint32_t number = 1268;
void* ptrAddress = &number;
Doesn't make a pointer to memory address 1268, like you seem to indicate you want it to. It makes a pointer to the integer where that 1268 is stored. You then overrun that storage by a lot, causing undefined behaviour, so after that it's game over.
If you want a pointer to a specific memory address:
void *ptrAddress = (void *)0x1268;
Make sure that address is legit in your environment/address space, though!
Second, strcpy works on null-terminated strings. You should probably use memcpy if you plan to work with a 4096 byte (non-null terminated) buffer. Note that means you can't print using printf (at least the way you're trying).
printf("%-4096s");
Should do it though.
I have a simple program where I have a string I've written in externally (in the case of this snippit, it's user created). And I'm trying to capitalize certain parts of it.
I first strtoked it by a delimiter, and attempted to capitalize it using the toupper function, however I seem to be getting segfaults doing it. Running valgrind provides no error, except simply states that:
Process terminating with default action of signal 11 (SIGSEGV)
==10180== Bad permissions for mapped region at address 0x4007B9
The code:
int main(void) {
char * test;
char * f;
char * s;
char * p;
test = "first:second:third:fourth:";
f = strtok(test,":");
for(p = f; *p; *p = toupper(*p), p++); //segfaults
printf("f is %s \n",f); //this should print "FIRST" as it should be capitalized
return 0;
}
You can't use strtok() on a string literal because it modifies it's argument, and you can't modify a string literal.
Nor can you modify it in this loop
for (p = f; *p; *p = toupper(*p), p++); //segfaults
You need an array or a dynamically allocated block of memory, both of which are writeable, with the array you can initialize using a string literal like this
char array[] = "This is a string literal, you are not allowed to modify it";
/* Now the arest of the code could work but ... */
You also need to check the return value of strtok() which is NULL when it doesn't find what you ask to find.
Using malloc() you can do this too
cosnt char *string_literal = "This is a sample string";
size_t length = strlen(string_literal);
char *buffer = malloc(length + 1);
if (buffer == NULL)
return -1; // Allocation failure.
memcpy(buffer, string_literal, length + 1);
// ^ copy the null terminator too
// Process your newly allocated copy here and,
free(buffer);
NOTE: About your original code with
f = s = p = test = malloc(sizeof(char * ) * 10);
malloc() is not used as a general initialization function, it's used to get a pointer to memory that you can use in the program, you can read/write from/to it. When you ask for memory with malloc() you ask for a specific (usually exact) ammount of bytes to be used in your program.
The returned pointer is then usable if it's not NULL, in case there is an error or the system has ran out of memory it will return NULL.
Your code has a major issue since all the pointers f, s, p and test point to the same memory address and also because you allocated an arbitrary size which might or not be the one you want/need.
When you free(f) and then go on and free(s), you are freeing the same pointer twice and you actually was doing it more than that. Calling free() twice on the same poitner invokes undefined behavior.
I am trying to get the first character of my char malloc like this:
char * str = malloc(sizeof(char)*100);
strcpy(str, op_mmin);
char *temp6=NULL;
strcpy(temp6,str[0]);
However, I am getting the following warning:
warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [enabled by default]
strcpy(temp6,str[0]);
^
Why can't I do str[0] to get the first char? I also tried to do this using ordinary arrays (eg. not a malloc) and I get the same error. How do I get the first char of this malloc (or array if you know that way too)?
Because str[0] is a character, not a string. And function strcpy must use two string (char *) as argument.
To resolve your problem, you can set temp[0] = str[0]; or use sprintf function, or use strncpy function
But you must allocate temp array before you want to use it.
Regarding char *temp6=NULL;
Here you're trying to tell the compiler, "Hey ! set up temp6 as a pointer to char but don't allocate memory for it. "
If you do something like strcpy(temp,str); later you will get segmentation fault because you are trying to write to memory you don't own.
In your case you didn't go so far to see the segmentation fault, the compiler caught another error which is mentioned by the other answerer, ie in the line :
strcpy(temp6,str[0]);
where the compiler expected second argument to be char* but you passed char.
You have to allocate memory to the pointer first, or point it to an array.
It is also possible to de-allocate the memory you have allocated for a pointer.
char* temp= malloc(sizeof(char) * 10) ; // allocating memory
temp='\0'; // In essence de-allocating the memory.
Below is a complete example.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
main()
{
char* temp= malloc(sizeof(char) * 10) ; //allocating memory enough to store 10 chars
char* str="abcdefgh"; // play safely - always store less than 10 characters. Consider that \0 will be appended to the end.
strcpy(temp,str);
printf("Temp : %s\n",temp);
char* str1="ijklmnop";
strcpy(temp,str);
printf("Temp : %s\n",temp);
temp='\0'; // In essence deallocating the memory.
printf("Temp : %s\n",temp);
strcpy(temp,str);
printf("Temp : %s\n",temp);
}
will give you the below result.
Temp : abcdefgh
Temp : abcdefgh
Temp : (null)
Segmentation fault (core dumped)
Also make sure that free(temp6) is placed at the end of your code to clean
up the memory.
Though this doesn't directly answer your question, hope it will be useful.
I solved the problem as follows:
char temp6 = op_mmin[0];
That's it! Now temp6 has the first char in op_mmin. Thank you all for your help.
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.
I have the following code.
#include <string.h>
#include <stdio.h>
int main()
{
char * l;
*l = 'c';
*(l+1) = 'g';
*(l+2) = '\0';
char *second;
strcpy(second, l);
printf("string: %s\n", second);
}
When I run it is says:
The output says "Segmentation fault"....any suggestions??
Thanks
l is an uninitialized pointer; you can't dereference it. You should allocate enough space to write its contents (statically (1) or dynamically (2)).
char l[3]; /* (1) */
#include <stdlib.h>
char *l = malloc(3); /* (2) */
It is the same error with strcpy: second is an unitialized pointer, you can't write into it.
You will learn to despise the Segmentation Fault error...
It's usually called when you try to access memory that is not yours. Most common occurrence would be when you try to access an array index that is out of bounds.
char *l just creates a pointer to a char. What you want is a string, which in C is defined as an array of chars. So when you try to access the next location in memory of whatever l is pointing to (which will probably just be garbage), you're going to access memory that isn't yours, thus Segmentation Fault
You could get memory with malloc or point the pointer to an already existing variable.
char word[3];
char *l;
l = word;
Now you can do such assignments:
*l = 'c';
*(l+1) = 'g';
*(l+2) = '\0';
but now that you want to copy it to another pointer, this pointer must be pointing to another string or you should allocate memory for it.
char *pointer_to_second;
char second[3];
pointer_to_second = second;
or if you prefer to get dynamic memory, change the 3 lines above be this one bellow:
char *pointer_to_second = malloc(sizeof(char) * 3);
after that you can do what you wanted:
strcpy(pointer_to_second, l);
But remember, if you are using a C compiler you must declare all variables at the beggining, otherwise you will get an error. If you are using a C++ compiler you won't have to concern about it.
Segmentation fault happens when you try to access a field that doesn't belong to your vector. For example, if you try this:
printf("The value in position 3 of my pointer is %c\n", *(l + 3));
You will probably get an error, because you pointer have 3 positions and you are trying to acess the 4th one.