Segmentation Fault With Char Array and Pointer in C on Linux
one
points directly to the string located in a read-only page. On the other hand, two
is an array allocated on the stack and is initialized with some constant data. At run time, the string in the read only section of the executable will be copied to the stack. What you are modifying is the copy of that string on the stack, not the read-only memory page.
At a higher level perspective, from the language point of view, "abcd"
is an expression of type const char*
and not char*
. Thus, modifying the value pointed by such an expression results in undefined behavior. The statement char* one = "something";
merely stores the pointer to the string in a variable (unsafely, since it's casting away const
modifier). The char two[] = "something";
is totally different. It's actually declaring an array and initializing it, much like int a[] = {1,2,3};
. The string in quotes here is the initialization expression.
Why do I get a segmentation fault when writing to a char *s initialized with a string literal, but not char s[]?
See the C FAQ, Question 1.32
Q: What is the difference between these initializations?
char a[] = "string literal";
char *p = "string literal";
My program crashes if I try to assign a new value top[i]
.A: A string literal (the formal term
for a double-quoted string in C
source) can be used in two slightly
different ways:
- As the initializer for an array of char, as in the declaration of
char a[]
, it specifies the initial values
of the characters in that array (and,
if necessary, its size).- Anywhere else, it turns into an unnamed, static array of characters,
and this unnamed array may be stored
in read-only memory, and which
therefore cannot necessarily be
modified. In an expression context,
the array is converted at once to a
pointer, as usual (see section 6), so
the second declaration initializes p
to point to the unnamed array's first
element.
Some compilers have a switch
controlling whether string literals
are writable or not (for compiling old
code), and some may have options to
cause string literals to be formally
treated as arrays of const char (for
better error catching).
Segmentation fault at the end of a *char array
Issues with your program: your index into the date components, i
, starts at 1 instead of 0 (is a terrible variable name for this purpose) and isn't updated consistently (first entry gets overwritten); the str()
array is a total mess allocation-wise (e.g. two dimensions, only one used); you assume the first strtok()
succeeds but that might not be the case with bad input; you don't test if the subsequent strtok()
calls succeed until after you've already used the result; you make no attempt to free()
the memory you malloc()
and even lose track of some.
Below is a rework of your original code that also adds some error checking and other niceties:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXIMUM_TOKENS 16
#define MAXIMUM_TOKEN_LENGTH 32
const char *separator = " ";
int main()
{
char string[(MAXIMUM_TOKEN_LENGTH + strlen(separator)) * MAXIMUM_TOKENS + 1]; // estimate
char *result = fgets(string, sizeof(string), stdin);
if (result == NULL)
{
fprintf(stderr, "An appropriate error message goes here.\n");
return EXIT_FAILURE;
}
/* strip final newline (\n) if present */
size_t last_index = strlen(string) - 1;
if (string[last_index] == '\n')
{
string[last_index] = '\0';
}
/* get the first token */
char *token = strtok(string, separator);
char *date_parts[MAXIMUM_TOKENS];
int date_parts_index = 0;
/* walk through other tokens */
while (token != NULL)
{
date_parts[date_parts_index++] = strdup(token);
token = strtok(NULL, separator);
}
/* print the tokens and free the strdup/malloc memory */
for (int i = 0; i < date_parts_index; i++)
{
(void) puts(date_parts[i]);
free(date_parts[i]);
}
return EXIT_SUCCESS;
}
USAGE
% date | ./a.out
Thu
Oct
20
09:58:00
PDT
2016
%
Although this is an appropriate use of strtok()
, be wary of it. It is an artifact of an earlier age and should be avoided in favor of safer, modern library functions like strsep()
and strtok_r()
.
Segmentation Fault accessing string in another function
From the C Standard (6.4.5 String literals)
7 It is unspecified whether these arrays are distinct provided their
elements have the appropriate values. If the program attempts to
modify such an array, the behavior is undefined.
So change the array of pointers to first characters of string literals
char *arr[2] = {"one","two"};
to a two-dimensional character array like for example
char arr[2][4] = {"one","two"};
Pay attention to that it is better to define the function like
char * revString( char *str )
{
for ( size_t i = 0, n = strlen( str ) ; i < n/2 ; i++ )
{
// swap two chars.
char temp = str[i];
str[i] = str[n-i-1];
str[n-i-1] = temp ;
}
return str;
}
Segmentation fault with char array member of struct using strcpy()
Till,
treeptr = &companyStructure;
Things look good. But then considering the fact that you have
NODE *head;
you need to allocate memory for head
. So most likely you've missed
treeptr->head = malloc(sizeof *treeptr->head);
before doing
strcpy(treeptr->head->name, "Ben");
Also, check [ this ] on why should you use strncat
instead of strcpy
.
Why does this C program throw a segmentation fault at runtime?
I'm declaring character array as char* string.
This is where your problems begin! Although pointers and arrays have some things in common, syntactically, they are not the same. What you are doing in the line copied below is declaring s
as a pointer to a char
and initializing that pointer with the address of the string literal you provide.
char* s = "random";
As a string literal, the compiler is allowed to (though not obliged to) allocate memory for that data in read-only memory; thus, when you attempt (later) to modify the character pointed to by (the address in) the s
variable (or any other pointer, such as your t
, which contains the same address), you will experience undefined behaviour. Some systems will cause your program to crash ("Segmentation fault"), others may silently allow you to 'get away' with it. Indeed, you may even get different result with the same code at different times.
To fix this, and to properly declare a character array, use the []
notation:
char a[] = "random";
This will declare a
as a (modifiable) array of characters (whose size is determined, in this case, by the initial value you give it - 7
, here, with the terminating nul
character included); then, the compiler will initialize that array with a copy of the string literal's data. You are then free to use an expression like *a
to refer to the first element of that array.
The following short program may be helpful:
#include <stdio.h>
int main()
{
char* s = "random";
*s = 'R'; // Undefined behaviour: could be ignored, could crash, could work!
printf("%s\n", s);
char a[] = "random";
*a = 'R'; // Well-defined behaviour - this will change the first letter of the string.
printf("%s\n", a);
return 0;
}
(You may need to comment-out the lines that use s
to get the code to run to the other lines!)
Related Topics
Can a Variable Be Declared Both Static and Extern
Lifetime of Object Is Over Before Destructor Is Called
Static Variable in the Class Declaration or Definition
Std::Async Won't Spawn a New Thread When Return Value Is Not Stored
Opencv on MAC Is Not Opening Usb Web Camera
Convert Integer to Binary and Store It in an Integer Array of Specified Size:C++
Possible Memory Leak Without a Virtual Destructor
Abstract Class VS Interface in C++
Initialize a Vector to Zeros C++/C++11
How Disastrous Is Integer Overflow in C++
Difference Between | and || , or & and &&
When Pass a Variable to a Function, Why the Function Only Gets a Duplicate of the Variable
What Is the Class Keyword Before a Function Argument
Why Does Sizeof(Int) Vary Across Different Operating Systems
Dependent Name Resolution & Namespace Std/Standard Library
How to Legally Reinterpret_Cast Between Layout-Compatible Standard-Layout Types