realloc() question

  • Thread starter Eric A. Johnson
  • Start date
E

Eric A. Johnson

Hi, I'm going through a book I got from the library. Admittedly, the book
is old -- it hails from 1994, and much has changed since then. However, I
would like to learn as much as possible from the book, as it covers some
very interesting topics.
I have an error that is a bit confusing to me, and the help I get from
pressing F1 on it is to general to be of much assistance. The following is
the code snippet that is giving me the error, followed by the error:

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

#define NAME_SIZE 35

void main(void)
{
long student_ctr = 0;
long ctr;
char *student_name = NULL;
while( (student_name =
realloc( student_name,
(NAME_SIZE * (student_ctr+1)))) != NULL )
{
/* ...Buncha stuff here... yada yada yada
}

--------------------Configuration: SamListing01_05 - Win32
Debug--------------------
Compiling...
SamListing01_05.cpp
C:\Program Files\Microsoft Visual
Studio\MyProjects\SamListing01_05\SamListing01_05.cpp(19) : error C2440: '='
: cannot convert from 'void *' to 'char *'
Conversion from 'void*' to pointer to non-'void' requires an
explicit cast
C:\Program Files\Microsoft Visual
Studio\MyProjects\SamListing01_05\SamListing01_05.cpp(19) : fatal error
C1903: unable to recover from previous error(s); stopping compilation
Error executing cl.exe.

SamListing01_05.exe - 2 error(s), 0 warning(s)

....I am primarily interested, of course, in how to modify this program so
that I can get it to compile and run without errors. If you need the rest
of the code, I will gladly supply it... but it pointed to the last line of
the while statement for the location of the error. I will be grateful for
any help... even tips on how this may not, for example, conform with ANSI C,
or differences between the C of '94 and of today. Thank you! :)

-- Eric A. Johnson
 
C

Chris Torek

void main(void)

The return-type of main() should be "int". (Using void here will
no doubt work on your system, and even on a lot of systems, but
"int" will work on *every* system. Plus, it is one character
shorter to type. Though then you have to add "return 0;" at the
end. :) )
char *student_name = NULL;
while( (student_name =
realloc( student_name,
(NAME_SIZE * (student_ctr+1)))) != NULL )

If realloc() returns NULL, the previously-allocated memory is
still allocated. For this reason, it is better to write, e.g.:

char *student_name = NULL;
char *new;

while ((new = realloc(student_name, ...)) != NULL) {
student_name = new;
...
}

This way, when the realloc() fails, you still have the old pointer,
which you can free() or continue to use, as appropriate. (For a
small program like this it will not really matter, but it is a good
habit to get into.)
SamListing01_05.cpp

Why did you name your C code ".cpp"? Suffixes ".c++", ".cpp", and
".C" (uppercase) generally indicate C++ code. You might as well
name it ".f77" or something. :)

(Plenty of good, valid C code does not work as C++ code, as much
as certain comp.lang.c trolls would have one believe otherwise.
Plenty of good, valid C code does work as C++ code too, but there
are few reasons to pretend one language is the other. The most
insidious cases are C programs whose meaning changes when compiled
with a C++ compiler, because C++ is a different language with
different scoping rules, for instance.)
 
E

Eric Sosman

Eric said:
Hi, I'm going through a book I got from the library. Admittedly, the book
is old -- it hails from 1994, and much has changed since then. However, I
would like to learn as much as possible from the book, as it covers some
very interesting topics.
I have an error that is a bit confusing to me, and the help I get from
pressing F1 on it is to general to be of much assistance. The following is
the code snippet that is giving me the error, followed by the error:

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

#define NAME_SIZE 35

void main(void)

int main(void), ever since 1989.
{
long student_ctr = 0;
long ctr;
char *student_name = NULL;
while( (student_name =
realloc( student_name,
(NAME_SIZE * (student_ctr+1)))) != NULL )
{
/* ...Buncha stuff here... yada yada yada
}

--------------------Configuration: SamListing01_05 - Win32
Debug--------------------
Compiling...
SamListing01_05.cpp
C:\Program Files\Microsoft Visual
Studio\MyProjects\SamListing01_05\SamListing01_05.cpp(19) : error C2440: '='
: cannot convert from 'void *' to 'char *'
Conversion from 'void*' to pointer to non-'void' requires an
explicit cast
C:\Program Files\Microsoft Visual
Studio\MyProjects\SamListing01_05\SamListing01_05.cpp(19) : fatal error
C1903: unable to recover from previous error(s); stopping compilation
Error executing cl.exe.

SamListing01_05.exe - 2 error(s), 0 warning(s)

It looks like the compiler thinks your code is supposed
to be C++ rather than C. Despite similarities in the first
parts of their names, the two languages are rather different.
(My first name and middle initial are also "Eric A," yet I'm
sure you'll agree you and I are rather different ...)

Try renaming your file from blah.cpp to blah.c; if that's
not the answer, check your compiler's documentation for the
proper incantation to tell it "This is C, not C++."
 
T

Tobias Oed

Eric said:
Hi, I'm going through a book I got from the library. Admittedly, the book
is old -- it hails from 1994, and much has changed since then. However, I
would like to learn as much as possible from the book, as it covers some
very interesting topics.
I have an error that is a bit confusing to me, and the help I get from
pressing F1 on it is to general to be of much assistance. The following
is the code snippet that is giving me the error, followed by the error:

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

#define NAME_SIZE 35

void main(void)
{
long student_ctr = 0;
long ctr;
char *student_name = NULL;
while( (student_name =
realloc( student_name,
(NAME_SIZE * (student_ctr+1)))) != NULL )
{
/* ...Buncha stuff here... yada yada yada
}

--------------------Configuration: SamListing01_05 - Win32
Debug--------------------
Compiling...
SamListing01_05.cpp
C:\Program Files\Microsoft Visual
Studio\MyProjects\SamListing01_05\SamListing01_05.cpp(19) : error C2440:
'='
: cannot convert from 'void *' to 'char *'
Conversion from 'void*' to pointer to non-'void' requires an
explicit cast
C:\Program Files\Microsoft Visual
Studio\MyProjects\SamListing01_05\SamListing01_05.cpp(19) : fatal error
C1903: unable to recover from previous error(s); stopping compilation
Error executing cl.exe.

SamListing01_05.exe - 2 error(s), 0 warning(s)

...I am primarily interested, of course, in how to modify this program so
that I can get it to compile and run without errors. If you need the rest
of the code, I will gladly supply it... but it pointed to the last line of
the while statement for the location of the error. I will be grateful for
any help... even tips on how this may not, for example, conform with ANSI
C,
or differences between the C of '94 and of today. Thank you! :)

How about differences between C and C++ ?
You most likely are using a c++ compiler (.cpp file extension?!) and
a void * isn't compatible with a char * in C++. You should use a c
compiler to compile your code and it will compile. As far as working
I'm more doubtfull (depending on what you do in the body of the loop): When
you exit this particular loop you have allocate until realloc fails, and
then you go ahead and leak all that memory.... Don't do a x = realloc(x,n)
but a

tmp = realloc(x,n);
if (tmp)
x = tmp
else
deal with problem


Tobias.
 
M

Michael Mair

Eric said:
Hi, I'm going through a book I got from the library. Admittedly, the book
is old -- it hails from 1994, and much has changed since then. However, I
would like to learn as much as possible from the book, as it covers some
very interesting topics.

If it covers C89, then it is new enough for discussing it here.
I have an error that is a bit confusing to me, and the help I get from
pressing F1 on it is to general to be of much assistance. The following is
the code snippet that is giving me the error, followed by the error:

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

#define NAME_SIZE 35

void main(void)
int main (void)

_never_ever_ void
Bring the book back if it told you to use void main (void)!
{
long student_ctr = 0;
long ctr;
char *student_name = NULL;
while( (student_name =
Careful! You are potentially throwing away your only pointer to the
storage pointed to by student_name.
realloc( student_name,
(NAME_SIZE * (student_ctr+1)))) != NULL )

The canonic way might look more like

char *tmp;
while ( (tmp = realloc(student_name, newsize)) != NULL )
{
student_name = tmp;
}

Otherwise, if NULL is returned by realloc(), student_name is
a null pointer but the memory it formerly pointed to does still
exist somewhere. A memory leak.
{
/* ...Buncha stuff here... yada yada yada
} }

--------------------Configuration: SamListing01_05 - Win32
Debug--------------------
Compiling...
SamListing01_05.cpp
C:\Program Files\Microsoft Visual
Studio\MyProjects\SamListing01_05\SamListing01_05.cpp(19) : error C2440: '='
: cannot convert from 'void *' to 'char *'
Conversion from 'void*' to pointer to non-'void' requires an
explicit cast

Your problem, however, is using a C++ compiler, telling it (via using
..cpp extensions) that you were compiling C++-code, and finally wondering
why it does not work even though C and C++ are different languages.

Compile the above using a C compiler or tell your compiler to compile
the files in its "C" mode (if it possesses one).

Michael
 
E

Eric A. Johnson

Malcolm said:
In C it is legal to convert from a void * to another pointer type without
a
cast, whilst in C++ it is not.

Since you gave your file a .cpp extension, MSVC++ is treating it as C++.

There's a debate on about whether C code should be written so that it
compiles under C++ or not. We don't have to get into this, excpet that
your
two options are to add the cast
The primary reason I'm compiling it as C++ is because I intend to, after I
get advanced enough in my knowledge of C, study C++ and learn for myself as
much of the differences between the two languages as I can. Nevertheless, I
will be more careful, and until I actually start studying C++, I will make
them simply .c rather than .cpp files.
student_name = (char *) realloc( ... )

and compile under C++,
That did the trick! :)
or change the filename to a .c extension and compile
as C.
I will also make sure to do this from now on.

A big thank you to everybody who wrote in! I greatly appreciate everyone's
help.

-- Eric A. Johnson
 
G

Goran Larsson

Eric A. Johnson said:
Compiling...
SamListing01_05.cpp

Why are you giving the source code to a C program the extension used
by C++ programs and then compiling with a C++ compiler? C and C++ are
not the same language.
Studio\MyProjects\SamListing01_05\SamListing01_05.cpp(19) : error C2440: '='
: cannot convert from 'void *' to 'char *'
Conversion from 'void*' to pointer to non-'void' requires an
explicit cast

This an example of the difference between C and C++. A C compiler would
never say this.
...I am primarily interested, of course, in how to modify this program so
that I can get it to compile and run without errors.

Start by compiling it with a C compiler.
 
M

Mysidia

Eric said:
Hi, I'm going through a book I got from the library. Admittedly, the book
is old -- it hails from 1994, and much has changed since then. However, I
would like to learn as much as possible from the book, as it covers
some

It seems as if you are using a C++ compiler.

This error would not occur if you were using a C compiler;
the cast is optional in C, but it is required in C++.

void* is the generic type which realloc() returns

Which is not the same as a char*, to the compiler
char *student_name = NULL;
while( (student_name =
realloc( student_name,
(NAME_SIZE * (student_ctr+1)))) != NULL )

Two things...

[1] Passing a null argument as the first parameter to realloc()
is not generally a good idea.

The general requirement is to allocate with malloc first.
Providing realloc with a NULL parameter will work on systems, on
others, bad things can happen.

[2] Casting looks like this:

while( (student_name =
(char *)realloc( student_name,
(NAME_SIZE * (student_ctr+1)))) != NULL )



The (char*) in front of realloc will force the data/pointer
to be interpreted as a char*


void* is the generic type.

-Jh
 
M

Malcolm

Eric A. Johnson said:
char *student_name = NULL;
while( (student_name =
realloc( student_name,
(NAME_SIZE * (student_ctr+1)))) != NULL )

Studio\MyProjects\SamListing01_05\SamListing01_05.cpp(19) : error C2440: '='
: cannot convert from 'void *' to 'char *'
Conversion from 'void*' to pointer to non-'void' requires an
explicit cast
In C it is legal to convert from a void * to another pointer type without a
cast, whilst in C++ it is not.

Since you gave your file a .cpp extension, MSVC++ is treating it as C++.

There's a debate on about whether C code should be written so that it
compiles under C++ or not. We don't have to get into this, excpet that your
two options are to add the cast

student_name = (char *) realloc( ... )

and compile under C++, or change the filename to a .c extension and compile
as C.
 
M

Michael Mair

Mysidia said:
[1] Passing a null argument as the first parameter to realloc()
is not generally a good idea.

The general requirement is to allocate with malloc first.
Providing realloc with a NULL parameter will work on systems, on
others, bad things can happen.

The standard says clearly that passing a null pointer as a first
argument to realloc() makes it behave like malloc().
Bad things only happen if you pass an uninitialised pointer which
does not per chance happen to be a null pointer or to have the same
representation as a pointer previously allocated via calloc()/malloc()
/realloc()...

Cheers
Michael
 
C

CBFalconer

Eric A. Johnson said:
.... snip ...
I have an error that is a bit confusing to me, and the help I get
from pressing F1 on it is to general to be of much assistance. The
following is the code snippet that is giving me the error, followed
by the error:

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

#define NAME_SIZE 35

void main(void)
{
long student_ctr = 0;
long ctr;
char *student_name = NULL;
while( (student_name =
realloc( student_name,
(NAME_SIZE * (student_ctr+1)))) != NULL )

So far you have two serious errors. main returns an int, not
void. Without that the behaviour is undefined. Also, if realloc
fails it returns NULL, which would overwrite the entity you are
trying to rewrite, losing it and creating a memory leak. If it
succeeds it returns a new pointer, which you must keep. Thus the
prototype statement is:

if (tmp = realloc(thing, newsize)) thing = tmp;
else {
/* whatever to recover from lack of memory */
}

.... snip ...
--------------------Configuration: SamListing01_05 - Win32
Debug--------------------
Compiling...
SamListing01_05.cpp

And here is another serious error. C source files have the
extension .c, not .cpp. Most systems, on seeing that .cpp, will
try to compile a C++ program, and that is another language
entirely.
 
A

Andrey Tarasevich

Mysidia said:
...
Two things...

[1] Passing a null argument as the first parameter to realloc()
is not generally a good idea.

The general requirement is to allocate with malloc first.

No, passing NULL as the first argument of 'realloc' is perfectly safe.
There's no "general requirement" to perform the initial allocation with
'malloc'. Furthermore, proper use of this feature of 'realloc' has a
great potential for making the code more compact, uniform and readable.
Providing realloc with a NULL parameter will work on systems, on
others, bad things can happen.

That would mean that those latter systems are seriously broken. And when
they are broken, a mere use of 'malloc' instead of 'realloc' is very
unlikely to put things in order.
[2] Casting looks like this:

As it was mentioned before, this program was obviously intended to be
compiled as C program. Casting the result of 'malloc'/'realloc' in C is
not required and actually not advised, since in it can be simply dangerous.
 
L

Lawrence Kirby

On Thu, 03 Feb 2005 17:36:31 -0500, Eric Sosman wrote:

....
int main(void), ever since 1989.

And before that. void didn't even exist in K&R 1.

Lawrence
 
A

Adam Warner

The primary reason I'm compiling it as C++ is because I intend to, after
I get advanced enough in my knowledge of C, study C++ and learn for
myself as much of the differences between the two languages as I can.

The languages are markedly different:

"Incompatibilities Between ISO C and ISO C++" by David R. Tribble
<http://david.tribble.com/text/cdiffs.htm>

Regards,
Adam
 
E

Eric Sosman

Lawrence said:
On Thu, 03 Feb 2005 17:36:31 -0500, Eric Sosman wrote:

...




And before that. void didn't even exist in K&R 1.

.... which means that `int main(void)' didn't exist
until 1989, right?

(By citing a date, I was just trying to point
out that the O.P.'s worries that his 1994 book might
be out of date w.r.t. subsequent changes in C are
reasonable, but that this particular matter was settled
long before his book came out.)
 
L

Lawrence Kirby

... which means that `int main(void)' didn't exist
until 1989, right?

But an int return type did, which is the important thing.
(By citing a date, I was just trying to point
out that the O.P.'s worries that his 1994 book might
be out of date w.r.t. subsequent changes in C are
reasonable, but that this particular matter was settled
long before his book came out.)

Even longer than your response suggests. :)

Lawrence
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Realloc destroys? 18
realloc 36
Problem with codewars. 5
realloc(): invalid next size 2
Is realloc good form ? 13
realloc & a segfault 0
malloc and realloc problem 1
realloc return value 12

Members online

No members online now.

Forum statistics

Threads
474,159
Messages
2,570,879
Members
47,416
Latest member
LionelQ387

Latest Threads

Top