Segmentation Fault with Char Array and Pointer in C on Linux

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 to p[i].

A: A string literal (the formal term
for a double-quoted string in C
source) can be used in two slightly
different ways:

  1. 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).
  2. 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



Leave a reply



Submit