LinuxQuestions.org
Visit the LQ Articles and Editorials section
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 04-26-2006, 11:57 AM   #1
kaz2100
Senior Member
 
Registered: Apr 2005
Location: Penguin land, with apple, no gates
Distribution: Debian testing woody(32) sarge etch lenny squeeze(+64) wheezy jessie
Posts: 1,433

Rep: Reputation: 83
How to survive without -fwritable-strings?


Hya, Penguins.

While I am working on some old tarball, I run into a run time error "Segmentation fault", which turned out to be violation of ANSI standard. I found that one of the options (gcc-3), -fwritable-strings can rescue this situation. However, this link http://www.linuxquestions.org/questi...ight=fwritable says that this option will go away in future. So, I am looking for the easist way to modify codes. Does anybody have good idea?

in summary
Code:
char *a = "dog";
char b[] = "Penguin";

int main(void){

*a = 'h'; /* This is the violation. */
b[1] = 'o'; /*This is NOT. */

return 0;
}
In this case, change *a to a[] is okay, but when *a is a member of struct or union, life is not easy.
Code:
struct trouble {
int i;
char *a;};

struct trouble thisIsNotGood[] = {{ 1, "abc"}, {2,"def"}, {3,"ghi"}}

Last edited by kaz2100; 04-26-2006 at 12:04 PM. Reason: mishandling
 
Old 04-26-2006, 12:23 PM   #2
addy86
Member
 
Registered: Nov 2004
Location: Germany
Distribution: Debian Testing
Posts: 332

Rep: Reputation: 31
Quote:
Originally Posted by kaz2100
While I am working on some old tarball, I run into a run time error "Segmentation fault", which turned out to be violation of ANSI standard.
A "segmentation fault" occurs, when you try to access memory areas you're not allowed to access, or access them in a way you're not allowed to (like, in your case, writing to non-writable memory).
Here's the solution: allocate enough memory for the string (malloc), copy it to this buffer (strcpy), then modify it. This way you don't have to change your struct declarations.
 
Old 04-26-2006, 01:13 PM   #3
paulsm4
Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Always allocate (potentially) writable data!

addy86 is absolutely correct.

Here's a note on the GCC "-fwriteable-strings" flag (said posting already three++ years old):
http://gcc.gnu.org/ml/java/2003-12/msg00165.html

I would strongly argue that both "b[]" (which happens to work under GCC) and "*a" (which fails) are bugs - the behavior is completely implementation-dependent (I'll betcha *both* will work under VC++, for example).

If you want to make a string writable (as addy86 said), you should explicitly allocate writable storage yourself (to make your intent clear):

Code:
#define MAX_STRING 80

  static char a[MAX_STRING] = "this will always work";

  char *b = malloc (MAX_STRING);
  if (b)
    strncpy (b, "this will always work, too!", MAX_STRING);

  static struct mystruct
  {
    char s[MAX_STRING];
  }
    mystruct = {
    { "this might even be valid, too!" }
  };
'Hope that helps .. PSM

Last edited by paulsm4; 04-26-2006 at 01:22 PM.
 
Old 04-26-2006, 09:09 PM   #4
destuxor
Member
 
Registered: Oct 2005
Posts: 51

Rep: Reputation: 16
Code:
#include <stdio.h>

int main ()
{
  char * s = "C reigns supreme.";
  *s = 'a';
  return(1);
}
The reason the above program will always crash is that the string C reigns supreme. is with the programs instructions themselves in memory and you cannot modify a program at runtime. This is probably demonstrated better with a small modification:
Code:
#include <stdio.h>

int main ()
{
  char * s;
  s = "C reigns supreme.";
  *s = 'a';
  return(1);
}
Again, the string is a part of the program itself, and the pointer s references this string within the program.
Think of the disaster you could pull off by manipulating pointers like this if you could modify code at runtime:
Code:
#include <stdio.h>

int main ()
{
  char * s = "C reigns supreme.";
  char * p = s - 0x16;
  * p = '0';
  return(1);
}
Here, you've moved 160 instructions up the stack (I think?) and could really mess things up.
 
Old 04-26-2006, 09:38 PM   #5
paulsm4
Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
The fact that GCC happens to put "C reigns supreme" in the executable's (read-only) .CODE section is an implementation detail - one that's not necessarily true of other compilers (MCVC++, for example).

The important point is to do what addy86 suggested (for which I tried to give a couple of examples):
http://www.linuxquestions.org/questi...43#post2218543
 
Old 04-27-2006, 09:46 AM   #6
kaz2100
Senior Member
 
Registered: Apr 2005
Location: Penguin land, with apple, no gates
Distribution: Debian testing woody(32) sarge etch lenny squeeze(+64) wheezy jessie
Posts: 1,433

Original Poster
Rep: Reputation: 83
Thanks for replies.

It does not look like to be "tweaking" solution, other than straightforward solution. (posted by addy86)

I do not know anything about "Inside gcc". My ANSI book says that
Code:
char b[] = "dog";

int main(void){

b[0] = 'h';

return 0;
}
is okay.

I am just looking for the easiest way to modidy an old program. (not my program, somebody else's)

So far,

#1. Modifing initializaion or struct definition is the last thing I want to do. (It is error prone.)

#2.
Code:
struct trouble {int i; char notGood[]}
is not an option. (It does not work.)

#3. Casting literals in initialization with (auto char*) results in error.
Code:
struct trouble thisIsNotGood[] = {
        {1,(auto char*)"abc"},
        {2,(auto char*)"def"}};
#4. Casting literals with (volatile char*) does not make difference.
Code:
struct trouble thisIsNotGood[] = {
        {1,(volatile char*)"abc"},
        {2,(volatile char*)"def"}};
#5. Use same definition and initialization and follow addy86

#6. Any other idea?
 
Old 04-29-2006, 01:29 AM   #7
randyding
Member
 
Registered: May 2004
Posts: 552

Rep: Reputation: 31
char *s="hello";
can be safely changed to
char s[]="hello";
which is handled by the compiler exactly like
char s[6]="hello";
That is ansi and all compilers I've ever seen work this way.
The data pointed to by s[] (not *s) can safely be modified because every time the function is entered the data is pre-initialized via memcpy from one of the const segments.
Should also be true when s[] is global but I haven't used that.

The only difference to your program should be when you use sizeof on the pointer.
In the *s case sizeof s returns 4, in the s[] case it returns 6.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
mdadm changes do not survive reboot blackdragonblood Linux - Software 4 02-12-2006 09:58 PM
how to find duplicate strings in vertical column of strings markhod Programming 7 11-02-2005 04:04 AM
Looks like we may survive the present after all. williamwbishop General 3 04-22-2005 09:30 AM
Squid doesn't survive reboot james.farrow Linux - Networking 1 10-21-2004 01:58 PM
Please help me survive routing with RH 9.0 and iptables pembo13 Linux - Networking 8 06-14-2003 11:36 AM


All times are GMT -5. The time now is 11:18 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration