Hello,
I did some expiremets with turning numbers with floating point to strings and vice versa,and bumped into something strange,here is the code:

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>

void main ()
{
    double num;
	num=310.589;
     char buffer [10]; 
	
	sprintf(buffer,"%f",num);
	buffer[7]=NULL;
	printf("using &num=\n");
	printf((char *)&num);
	printf("\nbuffer=\n");
	printf(buffer);
	printf("\nfragment of buffer=\n");
	printf((char *)&buffer[3]);
	scanf("%s",buffer);
	num=atof(buffer);
	num/=2;
	printf("\n%lf",num);
                _getch();
}

from some reason the folowing line causes a C0000005 exeption(if I understand correctly it means acces violation):

num=atof(buffer);

why does it happen?

p.s.
the intresting part is that when I compile it shows no errors and no warnings,
the problem appears only when I build.

Recommended Answers

All 20 Replies

printf((char *)&num);

is clearly an error; you are casting a double* to a char* (which is incorrect). unpleasant consequences would be the norm if you do such things. in C, to print out a double value, use

printf( "%f", num ) ;

instead.
atof is to be shunned; it has many problems. you would be much better off (and less likely to make errors) if you use C++ facilities where they are available. eg.

#include <string>
#include <iostream>
#include <sstream>
using namespace std ;

/*void*/ int main()
{
  double num = 310.589 ;
  /* char buffer [10]; */ string buffer ;
  /* sprintf(buffer,"%f",num); */ 
 { ostringstream stm ; stm << num ; buffer = stm.str() ; }
  // buffer[7] = *NULL;
  /*
  printf("using &num=\n");
  printf((char *)&num);
  printf("\nbuffer=\n");
  printf(buffer);
  printf("\nfragment of buffer=\n");
  printf((char *)&buffer[3]);
  */
  cout << "using &num= " << &num << "\nbuffer= " << buffer
       <<  "\nfragment of buffer= " << &( buffer.c_str()[3] ) << '\n' ;
  /* scanf("%s",buffer); */ cin >> buffer ;
  /* num=atof(buffer); */
  {
    istringstream stm(buffer) ;
    stm >> num ;
    if( !stm ) cerr << "conversion failed\n" ;
  }
  num/=2;
  /* printf("\n%lf",num); */ cout << num << '\n' ;
  /* _getch(); */ char ch ; cin >> ch ;
}

if you are preparing yourself for c++0x (you really should; final draft should be out in a few months), you could write

#include <string>
#include <iostream>
#include <sstream>
#include <boost/lexical_cast.hpp>
using namespace std ;
using namespace boost ;

int main()
{
  double num = 310.589 ;
  string buffer = lexical_cast<string>(num) ;
  cout << "using &num= " << &num << "\nbuffer= " << buffer
       <<  "\nfragment of buffer= " << &( buffer.c_str()[3] ) << '\n' ;
  cin >> buffer ; 
  try { num = lexical_cast<double>(buffer) ; }
  catch( const bad_lexical_cast& ) { cerr << "cast error\n" ; }
  num/=2;
  cout << num << '\n' ;
  char ch ; cin >> ch ;
}

note: lexical_cast used here is from boost; it would be part of c++0x

commented: Good stuff +9

lines 13 and 14 are incorrect. Should be this:

printf("using &num= %p\n", &num);

Your line 14 will probably cause access violation because printf() assums the first parameter is an ascii null-terminated string, and passing a pointer to a variable is not that kind of thingy.

[edit] ^^^ what vijayan121 said too. [/edit]

Well,I can sure tell you that it's not because of lines 13 and 14.
(first of all the program worked just fine with those lines before I added atof(),second of all when you talled me they can make trouble
I removed them completley from the code,and rebuilded the project,
it still gave the C0000005 exeption).
The realy weird part is that it works just fine in 'debbug' mode,
the problem is only in'release' mode,why is that?

oh,and thank you both for your advice,
vijayan121 I will try to do it without atof() as you suggested,thanks.

"Working" != "Bug Free".
Just because it didn't crash immediately on trying printf((char *)&num); doesn't mean that you can always get away with it. It is plainly wrong even if it didn't crash in your specific case.

Your program was broken at "void main" and the rest is just mere accident as far as I can see.

Start with the first identified problem and work your way through them.

> the intresting part is that when I compile it shows no errors and no warnings,
If you add enough casts, you can compile any old rubbish.
This is no exception.

> The realy weird part is that it works just fine in 'debbug' mode,
> the problem is only in'release' mode,why is that?
Because your code has undefined behaviour, which means any combination of working, not quite working, reformatting your hard disk, crashing in a heap is permissible.

Getting different results from different builds is a sure sign of doing something wrong.

If your code is correct, the ONLY difference between debug and release should be performance, nothing else.

Another problem I see in the original code is line 11 -- you have to make sure that the buffer size is big enough to hold all the digits that sprintf() will want to put into it. In your code buffer can only hold 9 characters plus the null terminator but sprintf() will attempt to fill it with 10 characters plus null terminator (310.589???) because the default is to display 6 decimals. So sprintf() at line 11 will cause buffer overflow and that function will scribble the remaining characters all over other memory.

Salem wrote:

Working" != "Bug Free".
Just because it didn't crash immediately on trying printf((char *)&num); doesn't mean that you can always get away with it. It is plainly wrong even if it didn't crash in your specific case.

Your program was broken at "void main" and the rest is just mere accident as far as I can see.

Start with the first identified problem and work your way through them.

> the intresting part is that when I compile it shows no errors and no warnings,
If you add enough casts, you can compile any old rubbish.
This is no exception.

> The realy weird part is that it works just fine in 'debbug' mode,
> the problem is only in'release' mode,why is that?
Because your code has undefined behaviour, which means any combination of working, not quite working, reformatting your hard disk, crashing in a heap is permissible.

Getting different results from different builds is a sure sign of doing something wrong.

If your code is correct, the ONLY difference between debug and release should be performance, nothing else.

Salem,as I already told,I deleted lines 13 and 14 completley from my code and rebuilded,it still gave the same error,so you can't blame those lines in this particular case.

The problem was solved when I replaced atof with strimstring.

As about the difference between 'debbug' and 'release',it's
not the first time I encounter with it on this particular compiler(VC++ 6.0).
You will be surprised to hear that when I compiled one of my programs
with the warnings set to level 4(highest),it's actually found 60 warnings
in a header file that I recived with the compiler!
They acctualy wrote headers that collide with their own compiler!

Ancient dragon,the intresting thing that it's worked as is the moment I replaced atof,but thanks I'll fix the code.

Rechecked the program,please accept correction,using stringstream
didn't gave any errors while building BUT it doesn't work the value of num doesn't change,remaines the same as at the beggining,the compiler just ignores that line:

stringstream(buffer)>>num;

But I developed my own way to convert from string to number(using very simple formula acctualy).


Salem wrote:

Your program was broken at "void main" and the rest is just mere accident as far as I can see.

Always wanted to ask you why it's wrong to write a main function that doesn't return a value(void mainer's are doomed...) ?

And if I make it return a value,where does that value arrive?

I've no idea what your code looks like now then. Describing your edits doesn't work for me.

Post your latest code and latest observations.

vijayan121 thank you for the links.
Salem,my program looked like this after the edits:

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<sstream>
#include<iostream>


using namespace std;

void main ()
{
    double num;
	
	num=310.589;
    char buffer [15]; 
	
	sprintf(buffer,"%f",num);
	
	printf("\nbuffer=\n");
	printf(buffer);
	printf("\npartial buffer=\n");
	printf((char *)&buffer[3]);
	printf("\nEnter a number:\n");
	//cin>>buffer;
	scanf("%s",buffer);
    //num=atof(buffer);  
	stringstream(buffer)>>num;
	
	printf("\n%f",num);

	_getch();



}

it compiled end builded with no problems,but when executing the program ignores the line:

stringstream(buffer)>>num;

and the initial value of num doesn't change(remains 310.589).

works fine on my machine; after kicking out <conio.h> and changing void main() to int main().
which compiler are you using? try stringstream stm(buffer) ; stm >> num;

> printf(buffer);
Never use a string you're not in complete control of as the format string for printf.
If anyone ever got a % character into that, your code would be seriously broken.
http://en.wikipedia.org/wiki/Format_string_attack

It's best to always use string constants for printf/scanf formats.

commented: nice read +11

Salem,thank you for the link,I will take this information in mind from now on.

vijayan121, I use VC++ 6.0,
I tried the edits you suggested,it started to give the error message again(actualy even when I removed only the:

_getch()

,the compiler gave an error message,weird isn't it).

Member Avatar for iamthwee

Another case of people reading advice but not really acting on it.

The very first thing you need to do is get rid of vc++ 6.0 and either get VC 2005 express or something like dev-cpp.

And then you can ignore all these little conclusions you are drawing, which quite frankly is going to be nonsense because of the tool you're using.

I thought maybe it will help if I quote the entire error message:

LINK : error : Internal error during ReadSymbolTable
ExceptionCode = C0000005
ExceptionFlags = 00000000
ExceptionAddress = 00465817
NumberParameters = 00000002
ExceptionInformation[ 0] = 00000000
ExceptionInformation[ 1] = 00F91184
CONTEXT:
Eax = 00F91180 Esp = 0012F61C
Ebx = 00000000 Ebp = 004A2678
Ecx = 00F91180 Esi = 00F60E94
Edx = 00000001 Edi = 004A2928
Eip = 00465817 EFlags = 00010212
SegCs = 0000001B SegDs = 00000023
SegSs = 00000023 SegEs = 00000023
SegFs = 0000003B SegGs = 00000000
Dr0 = 0012F61C Dr3 = 00000000
Dr1 = 004A2678 Dr6 = 00F91180
Dr2 = 00000000 Dr7 = 00000000
Error executing link.exe.
Tool execution canceled by user.

so, the "Exception code:" is ofcourse the number of the exception.

"Exception address" is the address in memory where the exception occured(please correct me if I'm wrong).

Eax,Ebx,Ecx,Edx- are the registers if I understand correctly(what their
contents means in this case I don't know).

Besides those stuff, I don't understand anything from the above error information,so I don't realy see the entire picture of the error.

Maybe someone can point me the right direction in analyzing this information?

iamthwee,
heard your advice before,tried the vc++ 2005 express,the problem is that it doesn't have the ability to work with resource files.
And I'm not sure whether my problem occures because of the compiler or because of the program itself.

Member Avatar for iamthwee

Really, have you installed the windows sdk which you have to download separately for vc 2005 express?

Or have you tried dev-cpp which already has support for resource files and is less than a 10MB download?

Really, have you installed the windows sdk which you have to download separately for vc 2005 express?

Or have you tried dev-cpp which already has support for resource files and is less than a 10MB download?

I will do that.

But I still would like to learn to analyze the error data I mentioned above.

>> I thought maybe it will help if I quote the entire error message:
>> LINK : error : Internal error during ReadSymbolTable
yes, it does help. the access violation is not when your code is running, but caused by link.exe which ships with vc++ 6.0.
you may be able to fix this by turning of incremental linking in your project settings (change link.exe switch /INCREMENTAL:NO if you are using a make file). and clean the intermediate files before the build. (in particular, delete any file with a .ilk extension). you could also disable use of precompiled headers; is also known to cause problems in vc++ 6.0 sometimes.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.