C++ program is crashing on re-assigning const static member variable using an int pointer


 
Thread Tools Search this Thread
Top Forums Programming C++ program is crashing on re-assigning const static member variable using an int pointer
# 1  
Old 01-19-2011
C++ program is crashing on re-assigning const static member variable using an int pointer

Hi,

Can any one tell me why my following program is crashing?

Code:
#include <iostream>
using namespace std;

class CA {
public:
    const static int i;
};

const int CA::i = 10;

int main() {
    int* pi = const_cast<int*>(&CA::i);
    *pi = 9;
    cout << CA::i << endl;
}

# 2  
Old 01-19-2011
Because the static constant value is probably in a read-only memory segment.

Patient: Doctor, it hurts when I do this.
Doctor: Don't do it.
# 3  
Old 01-19-2011
Global constants get hardware write-protection on lots of OSes. The program literally cannot write to them, memory map settings prevent it, the CPU itself knows you shouldn't and throws an exception if you try.

A static variable is as good as a global variable in most respects, this included.

Trying to get around this with trickery isn't a good idea. Even if you alter page protection to let you write, the program might ignore it when you do! The compiler, knowing the variable is a constant, will think "hmm, this variable will never change -- I can save 2 instructions per go by hardcoding it everywhere instead of reading it from memory..."
# 4  
Old 01-25-2011
Code:
#include <stdio.h>

static char			 _g_testChar[10] = "-GLOBAL";
static int			 _g_testInt = 1;

static const char	*_g_testConstChar = "-CONSTGLOBAL";
static const int	 _g_testConstInt = 2;

void main(int argc, char **argv)
{
	char				*testConstChar = "-CONSTCHAR";
	char				 testChar[10] = "-STACKCHAR";
	
	const int			 testConstInt = 3;
	int			 		 testInt = 4;
	
	char				*cPtr;
	int					*iPtr;
	
	cPtr = (argc > 1) ?
			( (argv[1][0] == 'c') ? testConstChar :
			  (argv[1][0] == 'C') ? _g_testConstChar : 
			  (argv[1][0] == 'g') ? _g_testChar : testChar )
			: testChar;
			
	iPtr = (argc > 2) ?
			( (argv[2][0] == 'c') ? &testConstInt :
			  (argv[2][0] == 'C') ? &_g_testConstInt :
			  (argv[2][0] == 'g') ? &_g_testInt : &testInt )
			: &testInt;
	
	printf("               Char            Int\n"
		   "Constant:      %-15p %p\n"
		   "Stack:         %-15p %p\n"
		   "Const Global:  %-15p %p\n"
		   "Global:        %-15p %p\n",
		   testConstChar, &testConstInt,
		   testChar, &testInt,
		   _g_testConstChar, &_g_testConstInt,
		   _g_testChar, &_g_testInt);
	
	printf("Trying char [%s]...\n", cPtr);
	*cPtr = '!';
	
	printf("Trying int [%d]...\n", *iPtr);
	*iPtr = 0;
	
	printf("%s\n"
		   "%d\n",
		   cPtr, *iPtr);
}

Play with this...it'll show you what your compiler "protects" and what it doesn't. Then look closely at the address table printed and look for the address space of your OS (for Linux it's here). What you'll probably see is that the variables you aren't allowed to change get put into the text segment, which can't be modified during runtime (easily).

On an aside, I have history with this because HP-UX was much more relaxed in this area. When we ported our HP-UX code to Linux we found out the hard way because our programs started crashing. It seemed innocent enough to us to have the essence of this:

Code:
void do_something(char *d)
{
  char *p;

  p = strtok(p, ":");
}

main()
{
  char *data = "this:is:some:data";

  do_something(data);
}

in the code.... Of course, since "this:is:some:data" is stored in the text segment, Linux crashed with the, not so helpful in this case, "segment violation". It dawned on us that the pointer was always in the 0x08 segment when it crashed, then we looked at the Linux address space and found that we were being bit by the compiler putting the string data in the text segment...always. Even worse, for strings it doesn't matter to the compiler whether the data is const or not. For integers, it seems to use const as a hint to go in the text segment if it's global, however stack constants aren't protected (and I suppose really can't be).

As far as Linux is concerned, it seems any quoted string in a source file is immutable and any static const is immutable. Any non-static const is only immutable if you follow the compiler's warnings if you're assigning a const variable's address to a non-const pointer variable.

Last edited by DreamWarrior; 01-25-2011 at 06:23 PM..
# 5  
Old 01-25-2011
Quote:
Originally Posted by DreamWarrior
As far as Linux is concerned, it seems any quoted string in a source file is immutable
There's a gcc option to let you write to strings, but this is generally considered a bad idea anyway.
# 6  
Old 01-25-2011
Quote:
Originally Posted by Corona688
There's a gcc option to let you write to strings, but this is generally considered a bad idea anyway.
Wish I would have know that back then, lol...would have saved us some re-work on a few applications.
# 7  
Old 01-31-2011
Quote:
Originally Posted by DreamWarrior
Code:
#include <stdio.h>

static char			 _g_testChar[10] = "-GLOBAL";
static int			 _g_testInt = 1;

static const char	*_g_testConstChar = "-CONSTGLOBAL";
static const int	 _g_testConstInt = 2;

void main(int argc, char **argv)
{
	char				*testConstChar = "-CONSTCHAR";
	char				 testChar[10] = "-STACKCHAR";
	
	const int			 testConstInt = 3;
	int			 		 testInt = 4;
	
	char				*cPtr;
	int					*iPtr;
	
	cPtr = (argc > 1) ?
			( (argv[1][0] == 'c') ? testConstChar :
			  (argv[1][0] == 'C') ? _g_testConstChar : 
			  (argv[1][0] == 'g') ? _g_testChar : testChar )
			: testChar;
			
	iPtr = (argc > 2) ?
			( (argv[2][0] == 'c') ? &testConstInt :
			  (argv[2][0] == 'C') ? &_g_testConstInt :
			  (argv[2][0] == 'g') ? &_g_testInt : &testInt )
			: &testInt;
	
	printf("               Char            Int\n"
		   "Constant:      %-15p %p\n"
		   "Stack:         %-15p %p\n"
		   "Const Global:  %-15p %p\n"
		   "Global:        %-15p %p\n",
		   testConstChar, &testConstInt,
		   testChar, &testInt,
		   _g_testConstChar, &_g_testConstInt,
		   _g_testChar, &_g_testInt);
	
	printf("Trying char [%s]...\n", cPtr);
	*cPtr = '!';
	
	printf("Trying int [%d]...\n", *iPtr);
	*iPtr = 0;
	
	printf("%s\n"
		   "%d\n",
		   cPtr, *iPtr);
}

Play with this...it'll show you what your compiler "protects" and what it doesn't. Then look closely at the address table printed and look for the address space of your OS (for Linux it's here). What you'll probably see is that the variables you aren't allowed to change get put into the text segment, which can't be modified during runtime (easily).

On an aside, I have history with this because HP-UX was much more relaxed in this area. When we ported our HP-UX code to Linux we found out the hard way because our programs started crashing. It seemed innocent enough to us to have the essence of this:

Code:
void do_something(char *d)
{
  char *p;

  p = strtok(p, ":");
}

main()
{
  char *data = "this:is:some:data";

  do_something(data);
}

in the code.... Of course, since "this:is:some:data" is stored in the text segment, Linux crashed with the, not so helpful in this case, "segment violation". It dawned on us that the pointer was always in the 0x08 segment when it crashed, then we looked at the Linux address space and found that we were being bit by the compiler putting the string data in the text segment...always. Even worse, for strings it doesn't matter to the compiler whether the data is const or not. For integers, it seems to use const as a hint to go in the text segment if it's global, however stack constants aren't protected (and I suppose really can't be).

As far as Linux is concerned, it seems any quoted string in a source file is immutable and any static const is immutable. Any non-static const is only immutable if you follow the compiler's warnings if you're assigning a const variable's address to a non-const pointer variable.
Do you mean, the write-protected char* and global data (BSS area) are put into text segment? I guess it is all part of "Data Segment". Please correct me.
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Programming

Declare member of struct as a pointer in c

I have a uint8_t *C = malloc(24*sizeof(uint8_t)); I need to send some integers and this *C to another node(in ad hoc network). So I am going to use a struct ` struct fulMsg { int msgType; int msgCount; //uint8_t *CC; } fulMsg_t; typedef struct fulMsg fulMsg_tt;` there is a method... (1 Reply)
Discussion started by: chap
1 Replies

2. Programming

Why this C program is crashing?

Hi, Why I am getting 'SIGSEGV' in the following code? char* p="abcde"; printf("%s", 3); // Segmentation Fault (core dump) Kindly help me to understand what exactly makes the program to crash or the reason for the crashing. (7 Replies)
Discussion started by: royalibrahim
7 Replies

3. Programming

question about int arrays and file pointer arrays

if i declare both but don't input any variables what values will the int array and file pointer array have on default, and if i want to reset any of the elements of both arrays to default, should i just set it to 0 or NULL or what? (1 Reply)
Discussion started by: omega666
1 Replies

4. Programming

Handle int listen(int sockfd, int backlog) in TCP

Hi, from the manual listen(2): listen for connections on socket - Linux man page It has a parameter called backlog and it limits the maximum length of queue of pending list. If I set backlog to 128, is it means no more than 128 packets can be handled by server? If I have three... (3 Replies)
Discussion started by: sehang
3 Replies

5. Programming

C++ type-casting a member variable in const methods

Is it permitted to type-cast a member variable passed in as a parameter in a member const method .. I am doing something like : in a return-type method () const { variable other = long(member variable) } this other assigned variable is not updating and I wonder if type-casting in such... (1 Reply)
Discussion started by: shriyer123
1 Replies

6. Programming

tolower (static pointer + malloc + realloc)

N00B here. This function would be easier using a char pointer along with free. But I wish to learn how to use char static pointers (they do not require free, right ?). How do I erase the content of a static pointer ? Terminating the string works but the static pointer's content is not being... (4 Replies)
Discussion started by: limmer
4 Replies

7. Red Hat

cast from const void* to unsigned int loses precision

Hello everey one, here i am attempting to compile a c++ project .it's throughing the following errors. my machine details are as follows: Linux chmclozr0119 2.6.18-53.el5 #1 SMP Wed Oct 10 16:34:19 EDT 2007 x86_64 x86_64 x86_64 GNU/Linux errors: ===== Generating... (0 Replies)
Discussion started by: mannam srinivas
0 Replies

8. Solaris

Assigning a static IP to NICs

Hi, I have checked the net and can't find why I can't ping the server nor can I ping any address inside or outside the network from the server (using serial connection). I can set up DHCP on the server and it gets an address of 192.168.1.118 and everything is fine. I cannot ping anything from... (10 Replies)
Discussion started by: sunfan
10 Replies

9. UNIX for Dummies Questions & Answers

int open(const char *pathname, int flags, mode_t mode) doubt...

hello everybody! I want to create a file with permissions for read, write, and execute to everybody using C, so I write this code: #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main(){ int fileDescriptor; fileDescriptor =... (2 Replies)
Discussion started by: csnmgeek
2 Replies

10. Programming

Accesing structure member:Error:dereferencing pointer to incomplete type

$ gcc -Wall -Werror struct.c struct.c: In function `main': struct.c:18: error: dereferencing pointer to incomplete type $ cat struct.c #include <stdio.h> #include <stdlib.h> #include <string.h> /*Declaration of structure*/ struct human { char *first; char gender; int age; } man,... (3 Replies)
Discussion started by: amit4g
3 Replies
Login or Register to Ask a Question

Featured Tech Videos