471,585 Members | 1,449 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,585 software developers and data experts.

Help converting malloc to new

Hi,
I am new to c++ and I am converting a c program to c++. I changed
malloc call to new and I am getting an exception violation. Here is the
relevant piece of code.

Compiler vc++ 7.0 (.Net 2003)

SQLINTEGER nCols;
SQLINTEGER cbColDataLength;
PBYTE* pColumnData = NULL;

=== C style ====
pColumnData = (PBYTE*) malloc(nCols * sizeof(PBYTE));
pIndicators = malloc(nCols * sizeof(SQLINTEGER));
pColumnData[nCol] = (PBYTE) malloc(cbColDataLength)

=== C++ style ====
pColumnData = new PBYTE [nCols * sizeof(PBYTE)];
pIndicators = new SQLINTEGER [nCols * sizeof(SQLINTEGER)];
pColumnData[nCol] = *(new PBYTE [cbColDataLength])

I tried using my logical understanding of pointers but the compiler
kept throwing me out. So looking at the compiler messsages I got it to
compile by using the above syntax. Please help me in figuring out if
this is correct.

Thanks
Prahalad

Feb 2 '06 #1
13 4380
On 2 Feb 2006 14:51:44 -0800, "ppateel" <pp*****@gmail.com> wrote:
Hi,
I am new to c++ and I am converting a c program to c++. I changed
malloc call to new and I am getting an exception violation. Here is the
relevant piece of code.

Compiler vc++ 7.0 (.Net 2003)

SQLINTEGER nCols;
SQLINTEGER cbColDataLength;
PBYTE* pColumnData = NULL;

=== C style ====
pColumnData = (PBYTE*) malloc(nCols * sizeof(PBYTE));
pIndicators = malloc(nCols * sizeof(SQLINTEGER));
pColumnData[nCol] = (PBYTE) malloc(cbColDataLength)

=== C++ style ====
pColumnData = new PBYTE [nCols * sizeof(PBYTE)];
"new" doesn't need to be told the size of the object being newed.
Therefore, this should be:
pColumnData = new PBYTE [nCols];

You are allocating an array of nCols elements of type PBYTE ... the
size is a given.
pIndicators = new SQLINTEGER [nCols * sizeof(SQLINTEGER)]; pIndicators = new SQLINTEGER [nCols];
pColumnData[nCol] = *(new PBYTE [cbColDataLength])
Oops ... you just dereferenced an uninitialized pointer! Besides, you
have a memory leak here because you lose the pointer returned by
new[]. Also, where is "nCol" defined? If you meant "nCols", you are
writing to the element one past the end of the array you just
allocated.

Otherwise, if it is between 0 and nCols-1, you can write:
pColumnData[nCol] = new PBYTE [cbColDataLength];

"new" returns a PBYTE* anyway, which is what pColumnData contains, so
there is no need to cast it (much less dereference it...???).
I tried using my logical understanding of pointers but the compiler
kept throwing me out. So looking at the compiler messsages I got it to
compile by using the above syntax. Please help me in figuring out if
this is correct.


Just be sure to call "delete []" instead of plain delete or free()
when you need to deallocate the arrays. Actually, you would be much
better off using std::vector<PBYTE> or std::vector<SQLINTEGER> for
your buffers.

--
Bob Hairgrove
No**********@Home.com
Feb 2 '06 #2
[Replying in comp.lang.c++...]

ppateel wrote:
I am new to c++ and I am converting a c program to c++. I changed
malloc call to new and I am getting an exception violation. Here is the
relevant piece of code.

Compiler vc++ 7.0 (.Net 2003)

SQLINTEGER nCols;
SQLINTEGER cbColDataLength;
PBYTE* pColumnData = NULL;

=== C style ====
pColumnData = (PBYTE*) malloc(nCols * sizeof(PBYTE));
pIndicators = malloc(nCols * sizeof(SQLINTEGER));
pColumnData[nCol] = (PBYTE) malloc(cbColDataLength)

=== C++ style ====
pColumnData = new PBYTE [nCols * sizeof(PBYTE)];
Drop the sizeof here. Should simply be

pColumnData = new PBYTE[nCols];
pIndicators = new SQLINTEGER [nCols * sizeof(SQLINTEGER)];
Drop the sizeof here as well. Should simply be

pIndicators = new SQLINTEGER[nCols];
pColumnData[nCol] = *(new PBYTE [cbColDataLength])
This one should probably be

for (int col = 0; col < nCol; ++col)
pColumnData[col] = new BYTE[cbColDataLength];
I tried using my logical understanding of pointers but the compiler
kept throwing me out. So looking at the compiler messsages I got it to
compile by using the above syntax. Please help me in figuring out if
this is correct.


It's not.

The original is unclear without the definitions of 'SQLINTEGER' or
'PBYTE' (at least in 'comp.lang.c++', do not cross-post to two groups
that have different areas of definitions). And the intention of the
allocations is murky, but I think I guessed it close...

V
--
Please remove capital As from my address when replying by mail
Feb 2 '06 #3
ppateel a écrit :
Hi,
I am new to c++ and I am converting a c program to c++. I changed
malloc call to new and I am getting an exception violation. Here is the
relevant piece of code.
IMO, this is not the correct way to convert it to C++.
You have to rethink it completely.


Compiler vc++ 7.0 (.Net 2003)

SQLINTEGER nCols;
SQLINTEGER cbColDataLength;
PBYTE* pColumnData = NULL;
What wonderful all uppercase type names.

=== C style ====
pColumnData = (PBYTE*) malloc(nCols * sizeof(PBYTE));
That's not C style.
You shouldn't cast malloc() in C.
pColumnData[nCol] = (PBYTE) malloc(cbColDataLength)
That's pretty weird, you're casting a void* to a PBYTE here.

=== C++ style ====
pColumnData = new PBYTE [nCols * sizeof(PBYTE)];
The "* sizeof(PBYTE)" shows that you don't know what the new operator
does. It's not a function like malloc().
It is smart enough to know how to get the size of PBYTE by itself.

pColumnData[nCol] = *(new PBYTE [cbColDataLength])


That is strange to me.
Maybe you should point out what you're trying to do.

Feb 2 '06 #4
On Fri, 03 Feb 2006 00:18:45 +0100, loufoque
<lo******@remove.gmail.com> wrote:
ppateel a écrit :
Hi,
I am new to c++ and I am converting a c program to c++. I changed
malloc call to new and I am getting an exception violation. Here is the
relevant piece of code.
IMO, this is not the correct way to convert it to C++.
You have to rethink it completely.


Compiler vc++ 7.0 (.Net 2003)

SQLINTEGER nCols;
SQLINTEGER cbColDataLength;
PBYTE* pColumnData = NULL;


What wonderful all uppercase type names.


They are macros defined in the standard ODBC header files. I think
they are common enough not to get all bent out of shape here, though;
people who ever did any ODBC development are familiar with them.

=== C style ====
pColumnData = (PBYTE*) malloc(nCols * sizeof(PBYTE));


That's not C style.
You shouldn't cast malloc() in C.


malloc returns a void*, so you have to cast it if you are compiling
the code in a C++ translation unit.
pColumnData[nCol] = (PBYTE) malloc(cbColDataLength)


That's pretty weird, you're casting a void* to a PBYTE here.


Depends on how PBYTE is defined, doesn't it?

=== C++ style ====
pColumnData = new PBYTE [nCols * sizeof(PBYTE)];


The "* sizeof(PBYTE)" shows that you don't know what the new operator
does. It's not a function like malloc().
It is smart enough to know how to get the size of PBYTE by itself.


True.
pColumnData[nCol] = *(new PBYTE [cbColDataLength])
That is strange to me.


Indeed.
Maybe you should point out what you're trying to do.


--
Bob Hairgrove
No**********@Home.com
Feb 2 '06 #5
On Fri, 03 Feb 2006 00:11:47 +0100, Bob Hairgrove
<in*****@bigfoot.com> wrote:
"new" returns a PBYTE* anyway (...)


This should read:

"new PBYTE[]" returns a PBYTE* anyway (...)

--
Bob Hairgrove
No**********@Home.com
Feb 2 '06 #6
Bob,
You are correct. This is part of a dll source code that is being used
as an extended stored procedure in SQL Server. The main function is to
connect to a IBM Mainframe using a third part ODBC driver. The reason
for converting it to C++ is to get the advantage of structured error
handling. The c code was getting an access violation and bringing the
SQLServer down. So I thought of moving it to C++ and trap the AV and
exit gracefully. It is a different issue that I am AVing at a different
location but atleast I exit gracefully without affecting the SQLServer.
If it is necessary I am more than happy to post the C source.
Now coming to what the dll does. It uses ODS library to connect to
the datasource and gets a resultset. Then it allocates an array of
pointers to the columns. there are nCols number of coulmns That is the
line

=== C code ====
// There are nCols number of columns so we have to allocate memory
to hold
// pointers to each column each of the size occupied by PBYTE.

pColumnData = (PBYTE*) malloc(nCols * sizeof(PBYTE));
pIndicators = malloc(nCols * sizeof(SQLINTEGER));
==============

here is more info on PBYTE , nCols

typedef unsigned char *PBYTE;
SQLSMALLINT nCols;
typedef short SQLSMALLINT;

After that there are call to ODBC functions to get the column
definations then we allocate memory for holding the rows

==== C code =======
// Allocate memory for row data.
if ((pColumnData[nCol] = (PBYTE) malloc(cbColDataLength)) ==
NULL)
{
srv_senddone(pSrvProc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0,
0);
goto SAFE_EXIT;
}

// Set all the allocated memory to 0 thus
//initializing the entire allocated memory
memset(pColumnData[nCol], 0, cbColDataLength);
================================================== ====
once the memory is allocated for the rows then another call to ODBC
function to get the row and store the data in the above allocated
memory. Then more logic to move the data from there to SQL Server
structures.
Hopefully I was lucid enough. If not I will try to answer any other
question. As I said if you want I will copy the C code. It is not
really big. The whole thing is less than 800 lines. I did not want to
make this post really big.

Thanks for the quick response. Hope fully I will be able to put this to
rest from all you help.

Prahalad

Feb 3 '06 #7

"ppateel" <pp*****@gmail.com> wrote in message
news:11*********************@g49g2000cwa.googlegro ups.com...
Bob,
You are correct. This is part of a dll source code that is being used
as an extended stored procedure in SQL Server. The main function is to
connect to a IBM Mainframe using a third part ODBC driver. The reason
for converting it to C++ is to get the advantage of structured error
handling. The c code was getting an access violation and bringing the
SQLServer down. So I thought of moving it to C++ and trap the AV and
exit gracefully. It is a different issue that I am AVing at a different
location but atleast I exit gracefully without affecting the SQLServer.
If it is necessary I am more than happy to post the C source.
Now coming to what the dll does. It uses ODS library to connect to
the datasource and gets a resultset. Then it allocates an array of
pointers to the columns. there are nCols number of coulmns That is the
line

=== C code ====
// There are nCols number of columns so we have to allocate memory
to hold
// pointers to each column each of the size occupied by PBYTE.

pColumnData = (PBYTE*) malloc(nCols * sizeof(PBYTE));
pIndicators = malloc(nCols * sizeof(SQLINTEGER));
==============

here is more info on PBYTE , nCols

typedef unsigned char *PBYTE;
SQLSMALLINT nCols;
typedef short SQLSMALLINT;

After that there are call to ODBC functions to get the column
definations then we allocate memory for holding the rows

==== C code =======
// Allocate memory for row data.
if ((pColumnData[nCol] = (PBYTE) malloc(cbColDataLength)) ==
NULL)
{
srv_senddone(pSrvProc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0,
0);
goto SAFE_EXIT;
}

// Set all the allocated memory to 0 thus
//initializing the entire allocated memory
memset(pColumnData[nCol], 0, cbColDataLength);
================================================== ====
once the memory is allocated for the rows then another call to ODBC
function to get the row and store the data in the above allocated
memory. Then more logic to move the data from there to SQL Server
structures.
Hopefully I was lucid enough. If not I will try to answer any other
question. As I said if you want I will copy the C code. It is not
really big. The whole thing is less than 800 lines. I did not want to
make this post really big.

Thanks for the quick response. Hope fully I will be able to put this to
rest from all you help.

Prahalad
Actually, your question has been answered.

malloc requires as a parameter the number of bytes to allocate.
new[] requires the number of elements.

MyStructure* MyArray = malloc( 10 * sizeof(MyClass) ); // Number of bytes.
MyClass* MyArray = new MyClass[10]; // Number of elements.

So, in your specific cases (presuming everything else is correct):
pColumnData = (PBYTE*) malloc(nCols * sizeof(PBYTE)); pColumnData = new PBYTE[nCols];
pIndicators = malloc(nCols * sizeof(SQLINTEGER));

pIndicators = new SQLINTEGER[nCols];

remember to use
delete[] pColumnData;
delete[] pIndicators;

when you're done with them.

Is this clear?
Feb 3 '06 #8
Jim
This was more in reply to this
<snip>
True.
pColumnData[nCol] = *(new PBYTE [cbColDataLength])
That is strange to me.

ndeed.
Maybe you should point out what you're trying to do.


Thanks for clarifying the difference between malloc and new. I know
now that
pColumnData = new PBYTE[nCols];
will give me an array of nCols each element holding a pointer to
PBYTE.

But I am stumped about
pColumnData[nCol] = (PBYTE) malloc(cbColDataLength)

If my understanding is correct, here pColumnData is an array to hold
the pointers which point to actual data in the returned columns. And in
the above statement it is allocating memory depending on the size of
each column and storing that pointer in the array elements. Then
another ODBC call will then fill that memory location with the actual
data.
For example if there are 2 columns one a char(10) and another an
integer, then in the C code the first element in pColumnData would hold
a pointer to char(10) value and the second element will hold a pointer
to an integer. In C you would findout what is the length of the each
column and set the cbColumnLength to that value and then do a malloc
and assign the address to element. Since the elements in the column
array point to different types of data I have a vague feeling that I
should be dealing with an array of void pointers and then assign
pointers of appropriate type to each of the elements. Right now I get
the feeling that my conversions to "new" are not functionally the same
as that of malloc.

Prahalad.

Feb 3 '06 #9
On 3 Feb 2006 01:55:09 -0800, "ppateel" <pp*****@gmail.com> wrote:
Jim
This was more in reply to this
<snip>
True.
pColumnData[nCol] = *(new PBYTE [cbColDataLength])
That is strange to me.

ndeed.
Maybe you should point out what you're trying to do.


Thanks for clarifying the difference between malloc and new. I know
now that
pColumnData = new PBYTE[nCols];
will give me an array of nCols each element holding a pointer to
PBYTE.

But I am stumped about
pColumnData[nCol] = (PBYTE) malloc(cbColDataLength)

If my understanding is correct, here pColumnData is an array to hold
the pointers which point to actual data in the returned columns. And in
the above statement it is allocating memory depending on the size of
each column and storing that pointer in the array elements. Then
another ODBC call will then fill that memory location with the actual
data.
For example if there are 2 columns one a char(10) and another an
integer, then in the C code the first element in pColumnData would hold
a pointer to char(10) value and the second element will hold a pointer
to an integer. In C you would findout what is the length of the each
column and set the cbColumnLength to that value and then do a malloc
and assign the address to element. Since the elements in the column
array point to different types of data I have a vague feeling that I
should be dealing with an array of void pointers and then assign
pointers of appropriate type to each of the elements. Right now I get
the feeling that my conversions to "new" are not functionally the same
as that of malloc.

Prahalad.


You are right. It's been a while since I did any ODBC, but it looks
like you are setting up one buffer for each column and calling
SQLBindColumn.

Here's a better way: calculate how many bytes you need for each column
and round up the numbers to the nearest multiples of whatever the
cache line size is on your machine. On x86 platforms, this is
typically 32. This will help to ensure that you have a minimum of
cache misses when reading and writing the data. Add up the resulting
lengths for all the columns, saving them somewhere so that you know
which element starts a new column. Allocate just one buffer for ALL
the columns by using std::vector<BYTE> (or std::vector<unsigned
char>)...you won't have to worry about new[] and delete[] if you do it
this way. Just make sure that you know when the vector gets destroyed.
If an exception occurs, and your vector is a class member, it will get
destroyed when the class is destroyed. Store the address to the first
element of each range of bytes in pColumnData[].

You will have to cast these pointers eventually when you get around to
reading and writing the data in C++, but that's unavoidable with
ODBC's C interface. If you have the time, it's probably worth it to
write little wrapper classes which take care of these details for you.

--
Bob Hairgrove
No**********@Home.com
Feb 3 '06 #10
In article <11**********************@g49g2000cwa.googlegroups .com>,
"ppateel" <pp*****@gmail.com> wrote:
Hi,
I am new to c++ and I am converting a c program to c++. I changed
malloc call to new and I am getting an exception violation. Here is the
relevant piece of code.

Compiler vc++ 7.0 (.Net 2003)

SQLINTEGER nCols;
SQLINTEGER cbColDataLength;
PBYTE* pColumnData = NULL;

=== C style ====
pColumnData = (PBYTE*) malloc(nCols * sizeof(PBYTE));
pIndicators = malloc(nCols * sizeof(SQLINTEGER));
pColumnData[nCol] = (PBYTE) malloc(cbColDataLength)

=== C++ style ====
pColumnData = new PBYTE [nCols * sizeof(PBYTE)];
pIndicators = new SQLINTEGER [nCols * sizeof(SQLINTEGER)];
pColumnData[nCol] = *(new PBYTE [cbColDataLength])

I tried using my logical understanding of pointers but the compiler
kept throwing me out. So looking at the compiler messsages I got it to
compile by using the above syntax. Please help me in figuring out if
this is correct.

Thanks
Prahalad


Don't change the C code from malloc to new, there is no reason to...

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Feb 3 '06 #11
Bob,
First thanks for all the help. You really dont know how much I
appreciate it ! But I still have not grasped all the details.
If you have the time, it's probably worth it to
write little wrapper classes which take care of these details for you.


That was the idea I started when I started writing this dll. This is a
general puprpose dll for sqlserver.Something like a SQL command line
interface. the user can type in any sql statement and the dll executes
the statement using SQLExecDirect. So I will not know neither the
number of columns nor the type of columns nor the number of rows. My
logic for handling the situation

call SQLNumResultCols

get number of columns
allocate array pointers to hold column data and the null indicators
(pColumnData = new PBYTE [nCols];
pIndicators = new SQLINTEGER [nCols]; )

for each column
cal SQLColAttribute to get column details (name, type, length etc)
allocate memory of column type and column length to hold data
call SQLBindCol to bind each column to the above memory location
call srv_describe to set up the column in sqlserver
next

do until no more rows
call SQLFetch
(this puts the data of each column in the memory location)
for each column
call srv_describe to set data in SQLServer
next
call srv_sendrow (to send the row to sql server)
next

do cleanup (release odbc resources, allocated memory)
call srv_sendrow with a SRV_DONE_MORE | SRV_DONE_COUNT
return

I have to figure out the whole std::vector<BYTE> (or
std::vector<unsigned
char>) concept as I am still a newbie when it comes to C++

Feb 3 '06 #12
Bob Hairgrove a écrit :
malloc returns a void*, so you have to cast it if you are compiling
the code in a C++ translation unit.


C code should be compiled with a C compiler.
And there are good reasons not to cast malloc.
http://www.cpax.org.uk/prg/writings/casting.php
Feb 4 '06 #13
Just an update. I finally was able to solve this issue. Thanks for
everybody in helping me understand the finer difference between malloc
and new especially Bob Hairgrove for providing more insight into ODBC
API .

Thanks
Prahalad

Feb 9 '06 #14

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Tarique Jawed | last post: by
3 posts views Thread by Robert Rota | last post: by
6 posts views Thread by TC | last post: by
21 posts views Thread by c | last post: by
156 posts views Thread by Lame Duck | last post: by
19 posts views Thread by mdh | last post: by
reply views Thread by XIAOLAOHU | last post: by
reply views Thread by leo001 | last post: by
reply views Thread by Anwar ali | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.