Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I am trying to write a program that converts a string to morse code. It currently works fine whenever input is a string literal but whenever I send a string as a variable I get a segmentation fault.
void morseCode(char* s)
{
for (int i = 0; s[i]!='\0'; i++)
printf("%s",morseEncode(s[i])); //morseEncode is a function which returns char* of morse code
}
int main()
{
int length = strlen("Hello");
char* s = (char*) malloc(length + 1);
s = "Hello";
morseCode(s); // Segmentation fault
morseCode("Hello"); // works fine
return 0;
}
This is a result of passing the variable s to morseEncode (which presumably modifies it) as modifying s is undefined behaviour. Specifically, modifying a string literal in such a manner is undefined behaviour per 6.4.5p6 [from C99:TC3]
It is unspecified whether these (string literal) arrays are distinct provided their
elements have the appropriate values. If the program attempts to
modify such an array, the behavior is undefined.
(text in parentheses added by me)
You might also want to take a look at this question.
You could instead declare s like so (with automatic storage duration).
char s[] = "Hello";
If you need s to be a pointer you could try
// Yes, sizeof(char) will always be 1 and you could remove it.
char *s = malloc(sizeof(char) * (strlen("Hello") + 1));
strcpy(s, "Hello");
// Your code that uses s here
free(s) // Important!
As an additional note #kaylum has pointed out that the original answer didn't provide a justification as to why calling the function in the two different ways produced different results. This is because the undefined behaviour you're running into just so happened to be undefined in a different way for each call. If I write out a similar program and compile it using gcc (with no flags) I end up running into a segfault both ways; on the other hand, compiling with clang -O both work! Its simply a product of whatever segment(s) of memory your specific compiler has decided you place each of those sequences of characters.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
It's an exercise of my college. The goal is to make illegal memory store and illegal memory access and print it in char. However, using MALLOC has memory adresses doesn't store 'y', and using char x works. Why this difference? But when I use char x it shows me what I want, however, in the end show me this text "* stack smashing detected *: terminated
Abortado (imagem do nĂșcleo gravada)"
void ilegal_store(char *u)
{
for(int i=0;i<100;i++){
*(u+i) = 'y';
}
}
void ilegal_reading(char *u)
{
for(int i=0;i<100;i++){
printf("%d = %d\n",i,*(u+i));
}
}
void main()
{
//char x; WORKS
char *x=(char *)malloc(sizeof(char)); //USING MALLOC HAS ADRESSES WHICH DOESN'T STORE THE 'y' by ilegal_store();
if(x!=NULL){
ilegal_store(x); //use &x when not pointer
ilegal_reading(x); //use &x when not pointer
}
}
The C standard does not permit you to dereference a pointer to memory that you don't own. The behaviour on attempting to do so is undefined. Undefined behaviour manifests itself in many curiosities such as "working" sometimes, not "working" sometimes, or the compiler even erasing that particular branch: it's allowed to assume that undefined behaviour does not occur.
It's possible that you will not get a crash at exactly the first undefined dereference. Because the output of printf is frequently buffered and therefore often in lag of the code generating the output, you might be able to produce a extra output for the uncommented case by flushing the buffer after every iteration using fflush(stdout). The presence of the newline character in the case you cite as working can also flush the buffer. It's probably the newline character that is producing the different behaviour.
Finally, however this is dressed up, you are circumventing contraints the language places on you. If you want to circumvent these constraints then you need to use a different language. Many C compilers support inline assembly. That's what you need to use in this instance.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'v encountered "Segmentation fault (core dumped)" when compile my C program in *nix. I've narrowed the mistake to this line (without this line my program can run):
strcpy(con[count], "1234");
Before that, I declared con as:
char *con[30];
And count is always smaller than 30.
What's wrong with this line? How should I change it?
char *con[30];
declares an array of 30 pointers to strings. This is not what you need. It fails because you then try to copy to the first string, but did not allocate the first string (only a pointer to it)
You need
char con[30];
and then
strcpy(con, "1234");
Or (as Lee Danial points out) you might have wanted an array , in which case you need
char *con[30];
then
con[count] = strdup("1234")
or
con[count] = "1234"
The first one allocates a string and copies it for you (a combination of malloc and strcpy). The second one just points at the supplied literal, it doesn't make a copy. Hard to say which is 'best' for you.
PS strdup is equivalent to
x = malloc(strlen(str) + 1);
strcpy(x, str);
return x;
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
i'm getting segmentation fault core dumped when im using strtok at the next code part. the code is getting debugged but when I run it I get the segmentation fault. How can I fix it?
struct{ char *name;
void(*func)(void);
}cmd[]={
{"read_cm",read_cm},
{"NA",NULL}
};
int d;
char *s="_\n";
char *token2;
for(d=0;cmd[d].func!=NULL;d++)
{
token2=strtok((cmd[d].name),s);
}
You may not modify a string literal. Any attempt to modify a string literal results in undefined behavior.
The standard C function strtok tries to insert a terminating zero while splitting a string into substrings.
To resolve the problem use a character array instead of the pointer name. Or allocate memory dynamically and copy a string to the allocated memory pointed to by the pointer name.
For example
struct
{
char name[8];
void(*func)(void);
} cmd[] =
{
{ "read_cm", read_cm },
{ "NA", NULL }
};
Another approach is to use standard C functions strcspn and strspn instead of strtok to find substrings.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have this two arrays, codeblocks doesn't give me any build error but whenever I run it, it gives "Segmention fault" and it shuts the program down I've debugged it and found out I can't change values from names1 this way but changing names2 this way works just fine, is there a way to make this work? If yes how do I make troca work for names1?
void troca(char* frase){
unsigned i=0;
while(*(frase+i)!='\0') {
if(*(frase+i)=='O') {
*(frase+i)='0';
}
i++;
}
}
int main(){
char *names1[]={"JOAO","MANUEL","ROBERTO","ZE"};
char names2[][51]={"JOAO","MANUEL","ROBERTO","ZE"};
unsigned i;
for(i=0;i<4;i++) {
troca(names2[i]);
}
return 0;
}
The difference is:
names1 is declared simply as an array of string pointers without other defined characteristics. Using string literals here will put the string literals into a section in your executable file which is read-only, because the compiler can this way re-use them. For example, when you use char* a = "abc"; char* b = "abc"; then most likely a and b will have equal memory addresses as values. This means you can't modify them, so you get a "Segmentation fault" (another name for the same error is "Access Violation").
names2 is declared as an array of arrays of chars. Assigning a string literal there will copy the data of the strings into the array, and since there is no const thing in play in your code, the array has to be mutable, so in turn your strings stored in the char arrays are mutable as well.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am getting Segmentation fault after return executes. Why is it coming after return and not in strcpy?
int main()
{
char a[2];
strcpy(a,"0123456789101112131415161718192021222324252627282930");
printf("%s\n",a);
return 0;
}
I am getting Segmentation fault after return executes. Why is it coming after return and not in strcpy?
You have made a common mistake called a buffer overflow. This results in undefined behavior, which is a standards answer. However, if you understand how a typical machine uses a stack, you can understand why it crashes when you return. Most CPUs use a down ward growing stack. So before you call strcpy, the stack is something like,
sp + 0 : a[0]
sp + 1 : a[1]
sp + 2 : padding
sp + 3 : padding
sp + 4: return address (four bytes)
The compiler machinery creates a call frame each time you use a function in 'C'. The return address exists as part of stack where the compiler allocates space for your a[] array. As it is under-sized for the string copy, you over-write the return address. This value isn't used until you return. The return address will be overwritten with something like the value 0x34353637 which is the binary pointer for the ASCII text '4567'.
It is advisable to use something like strncpy or an alternative. For example,
strncpy(a,"012345678...", sizeof(a));
a[sizeof(a)-1] = 0; /* ensure the string is terminated. */
Obviously you need to increase the size of your 'a' array if you want the full string to be printed.
Why is it coming after return and not in strcpy?
You get the segmentation fault when main returns because you overwrite critical data (saved frame pointer and return address) in the stack frame of main function and not in the stack frame of strcpy function.
As others already said, you invoke undefined behavior and anything can happen: from nothing to a nuclear war.
You're trying to load a string with a lot more than 2 characters into a char array that only holds 2 characters. This will cause a segmentation fault, since you are overwriting the memory allocated for the char array, which can also cause undefined behavior.
Your program overwrote the buffer, that would cause undefined behavior, which means literally anything could happen.