3 Replies Latest reply on Sep 1, 2005 11:06 PM by 807575

    Errors with String Literals

    807575
      I've defined a structure with char* values. A static array of these structures are initialized with string literals in the .cpp file.

      Example.h
      typedef struct strExample
      {
      char* _value1;
      char* _value2;
      } t_strExample;

      class Example
      {
      static t_strExample arrayExample[];
      };

      Example.cpp
      // Initialization of arrayExample
      t_strExample Example::arrayExample[] = {
      { "Val1-Data1", "Val2-Data1"},
      { "Val1-Data2", "Val2-Data2"},
      { "Val1-Data3", "Val2-Data3"}
      };

      During compile this results in compiler warnings:
      "Warning: String literal converted to char* in initialization."
      This warning is eliminated if I set the compiler flag:
      -features=no%conststrings

      However, the true issue is at runtime.

      When I attempt to print the values of the array, there is a segmentation fault.
      functionExample()
      {
      for( int i=0; i {
      printf(" %d) Value1(%s) Value2(%s)\n",
      i, arrayExample._value1, arrayExample._value2);
      }
      }
      This code is being ported from a Window's environment where it works perfectly fine. Would anyone have pointers to help me solve this runtime segmentation problem when I attempt to print the values of the array?

      I'm working with the Sun ONE Studio 8 Compiler
        • 1. Re: Errors with String Literals
          807575
          In C++, a literal string has type "array of const char". You are using a literal to initialize a pointer to non-const. The compiler is warning you about a potential run-time error. You are allowed to assign via the pointer, but trying to change a const value has undefined results.

          By default in Sun C++, literal strings are put into read-only memory. You will get an immediate program crash if you attempt to modify a literal string, such as by assigning via the pointer.

          If you don't intend to change what the "value" members of the struct point to, you should delcare them as "const char*". If you then attempt to assign via the pointers, you will get a compile-time error instead of a run-time crash.

          The -features=no%conststrings option causes literal strings to be put into read-write memory, so you won't get an immediate program crash when you modify the string. But modifying the literal could cause a program crash somewhere else. Example:
          char*p="1234";
          p[4]='5';
          printf("%s", p);
          In this example, we over-write the terminating null of "1234" with '5', so printf just keeps trying to print characters until it (by accident) finds a null byte, or runs off the end of the program and crashes.

          If you intend to modify what the "value" members point to, you should allocate memory and copy the literal strings into the allocated memory.
          • 2. Re: Errors with String Literals
            807575
            Why does the code cause a fault, when the author is attempting to only read the contents, via the printf, not modify (write) it?

            Jeff
            • 3. Re: Errors with String Literals
              807575
              Do you mean the example at the end of the previous posting?

              The programmer replaced the terminating null of the string with a non-null character.

              The %s modifier to printf says to print characters from the starting address up to the next null byte. After printing 5 characters from the string, printf continues to read and print characters, looking for a null byte. There is no guarantee that a null byte will be seen before hitting the end of allocated memory. At that point, you get a memory violation and the program crashes.

              If it happened that there was a null byte before the end of memory, the program would not crash at that point, but printf would output some number of inappropriate characters. You might wind up printing a control character to a device that caused misbehavior. If you were using sprintf instead of printf, you could write beyond the end of the allocated sprintf buffer, with unpredictable results.