Garbage in a char* (getting rid of it??)

  • Thread starter leonard.guillaume
  • Start date
L

leonard.guillaume

Hi guys,

I use dynamic char arrays and I'm trying to get rid of the garbage in
it. Let me show you the code and then I'll explain more in details.

----------------------------------------------------------------------------------------------------
CFile oFile("User.tcx", CFile::modeRead);
CRijndael oDecrypt;
long size;
char* buffer,* buf;

size = oFile.GetLength();

buffer = new char[size];
memset(buffer, 0, size);

oFile.Read(buffer,size);
oFile.Close();

buf = new char[size];
int size_t = strlen(buf);
memset(buf, 0, size);

oDecrypt.Decrypt(buffer, buf, size, CRijndael::CBC);

CFile iFile("test_r.xml", CFile::modeCreate|CFile::modeWrite);
iFile.Write(buf, strlen(buf));
iFile.Close();
----------------------------------------------------------------------------------------------------

Ok so the big idea of the code above is :

1. Reads User.tcx which is a Rijndael encoded file and load everything
in a buffer which has the size of the file.
2. Throw the buffer to the Decrypt function which will use a second
buffer (*buf) to write the results. The *buf variable has the same size
as the *buffer and the encrypted file.
3. Write the results in *.buf to an XML file by using strlen(buf) in
order to avoid too many caracters to be written.

After that, I can see my whole XML file into the source file, but the
XML won't show up in a browser. All the code is there but I always get
garbage like this at the end of the file :

ýýýý

The weird thing is that strlen(buffer), strlen(buf) are giving me 2864
as the size of the buffers. But, the variable "size" which is the size
of the file in size = oFile.GetLength(); is showing 2848. I don't know
if this has something to do with the garbage, but I can assure you that
I do not resize my arrays.

In fact, if I do this :

buffer = new char[2848];
int len = strlen(buffer);

it will still gives me 2864 as strlen(buffer). Of course, if I use
memset the length goes down to 0, but the fact is that even if I
hardcode my dynamic arrays to 2848, they will size to 2864. Again, I
don't know if this has something to do with the garbage, but I'm
curious.


Bottom line, How can I get rid of the garbage into my written file ? I
don't really care having it in the buffer or not, as long as it's not
in the XML output file. And I must use dynamic arrays, since not all
files has the same size.

Thanks for any help :)

Guillaume
 
J

Jakob Bieling

(e-mail address removed) wrote:

[whoops, i accidently replied to your email account .. sorry about that]
buffer = new char[2848];
int len = strlen(buffer);

it will still gives me 2864 as strlen(buffer). Of course, if I use
memset the length goes down to 0, but the fact is that even if I
hardcode my dynamic arrays to 2848, they will size to 2864. Again, I
don't know if this has something to do with the garbage, but I'm
curious.

'buffer' is an array of random character values. Now this is what
strlen
does: it checks each element (where the value is garbage still!) and
looks
for the character that is 0. Since you array contains random junk, it
might
(and in your case will) never find it inside your array. So it reads on
in
memory you do not even own. Long story short: do not use strlen on an
array,
if you are not *sure* that there is a 0 inside your array. You need to
differenciate between a char-array and a C-string. A C-string is be
contained in a char-array, if and only if the char array contains a 0.
If
not, you do not have a C-string and may (must!) not use str* functions
on
it.

The reason strlen returns 0 after memset with 0 is: strlen finds the
0
right at the beginning -> length of the C-string is 0.

You might also have a look into std::string and std::vector.

hth
 
L

loufoque

I use dynamic char arrays and I'm trying to get rid of the garbage in
it.

Better get rid of the garbage in your code first.
Too many memory leaks and too much nonsense.

Not using C stuff like strlen would be a good idea.
 
B

Ben Pope

The weird thing is that strlen(buffer), strlen(buf) are giving me 2864
as the size of the buffers. But, the variable "size" which is the size
of the file in size = oFile.GetLength(); is showing 2848. I don't know
if this has something to do with the garbage, but I can assure you that
I do not resize my arrays.

In fact, if I do this :

buffer = new char[2848];
int len = strlen(buffer);

strlen works on C style strings (null terminated char arrays), not
arbitrary arrays of uninitialised chars.
it will still gives me 2864 as strlen(buffer).

On my platform it doesn't, it crashes.
Of course, if I use
memset the length goes down to 0, but the fact is that even if I
hardcode my dynamic arrays to 2848, they will size to 2864.

Your arrays do not "size" to 2864, just because you are incorrectly
using a function. They are still 2848 long, capable of storing a string
of 2847 characters (and a null char at the end). Accessing anything
beyond this (by using strlen) is undefined behaviour.
Again, I
don't know if this has something to do with the garbage, but I'm
curious.

Of course it is to do with the garbage. You're effectively using an
uninitialised string.
Bottom line, How can I get rid of the garbage into my written file ?

Always initialise your variables.
I
don't really care having it in the buffer or not, as long as it's not
in the XML output file. And I must use dynamic arrays, since not all
files has the same size.

What's wring with std::string? If you don't know when to use strlen and
how to initialise your C style strings, you will really struggle with
the more complicated aspects of dynamic length C style strings. In
fact, I don't think you will be able to do it at all.

Don't feel bad though, std::string was invented for precisely this
reason. C style strings are hard and unnecessary in almost all cases.

Ben Pope
 
L

leonard.guillaume

Thanks for your reply.

Now I much more understand what strlen does and why it was doing this.

I'm gonna try using CString instead. Maybe I'll have more luck. I'll
keep you posted if it worked or not
 
B

Ben Pope

Thanks for your reply.

Now I much more understand what strlen does and why it was doing this.

I'm gonna try using CString instead. Maybe I'll have more luck. I'll
keep you posted if it worked or not

Don't bother. CString is not topical here.

Ben Pope
 
J

Jakob Bieling

I'm gonna try using CString instead

Be aware of the fact that CString is a proprietary 3rd party string
class provided by Microsoft. The Standard C++ language has its own
string type, called "string" inside the std namespace. Google for it.

hth
 
L

leonard.guillaume

CString or string doesn't work with the Decrypt function. This function
uses this prototype : Decrypt(char const* in, char* result, size_t n,
int iMode).

Is there ANY way to filter the junk in a char array? I know I'm still a
jerk by trying to use char* again but it's the simpliest way with the
Decrypt function. As exemple, can we do this ?

memset(buffer,0,/*from the end of the good stuff to the end of the
array*/) ?
 
R

rossum

CString or string doesn't work with the Decrypt function. This function
uses this prototype : Decrypt(char const* in, char* result, size_t n,
int iMode).

Is there ANY way to filter the junk in a char array? I know I'm still a
jerk by trying to use char* again but it's the simpliest way with the
Decrypt function. As exemple, can we do this ?

memset(buffer,0,/*from the end of the good stuff to the end of the
array*/) ?
A suggestion. Use std::string for everything up to the point that you
call Decrypt(). You can extract a C-style string from a std::string by
using the c_str() method.

std::string myString = "This is some text.";
char * cString = myString.c_str();

This will give you a properly formatted C-style string without garbage
in it since std::string initialises itself properly and will resize
itself as needed. Much easier to work with.

rossum
 
P

Paul

CString or string doesn't work with the Decrypt function. This function
uses this prototype : Decrypt(char const* in, char* result, size_t n,
int iMode).

The first parameter is a const char *. This is compatible with
std::string::c_str().
The second parameter is compatible with an appropriately sized
std::vector<char>, and passing a pointer to the first element in the vector
buffer.

So the following should be safe to use, if I am correct in my assumptions of
Decrypt():

#include <string>
#include <vector>
//...
int some_buffer_size;
//...
// Assuming that some_buffer_size has a value:
//...
std::string sIn = "jirojrewu024j3024lkf0u94320";
std::vector<char> sOut( some_buffer_size);
//...
Decrypt( sIn.c_str( ), &sOut[0], /* other parameters */ );
//...

So you can do this whole thing without dynamic allocation.

- Paul
 
J

Jakob Bieling

rossum said:
A suggestion. Use std::string for everything up to the point that you
call Decrypt(). You can extract a C-style string from a std::string
by using the c_str() method.

std::string myString = "This is some text.";
char * cString = myString.c_str();

This you cannot do, because c_str() returns a 'char const*'.

In this case you would need a const cast, if and only if you are
sure that nobody will modify the string through the non-const pointer.
If you cannot be sure, either copy the contents to a vector and pass the
address of the first element of it or store your C-string in a vector
right from the start.

regards
 
B

Ben Pope

CString or string doesn't work with the Decrypt function. This function
uses this prototype : Decrypt(char const* in, char* result, size_t n,
int iMode).

Is there ANY way to filter the junk in a char array? I know I'm still a
jerk by trying to use char* again but it's the simpliest way with the
Decrypt function. As exemple, can we do this ?

You are using an uninitialsed C style string.

I strongly suggest you do not use a C style string.

Failing that I strongly suggest you go and read how to use C style strings.

You need to initialise your string. That is quite easy.
memset(buffer,0,/*from the end of the good stuff to the end of the
array*/) ?

There is no need to set the entire string to zeros, all you need is to
null terminate your string.

Here, I'll initialise a string for you, but be warned that if you do not
go and read how to use C style strings this will do you more harm than good.

#include <cstring>
#include <iostream>

int main() {
// create an initialised buffer for use as a C string
char buffer[1024] = "";
// check it's length
std::cout << std::strlen(buffer) << std::endl;
}

Ben Pope
 
R

rossum

Jakob said:
This you cannot do, because c_str() returns a 'char const*'.

In this case you would need a const cast, if and only if you are
sure that nobody will modify the string through the non-const pointer.
If you cannot be sure, either copy the contents to a vector and pass the
address of the first element of it or store your C-string in a vector
right from the start.

regards
Whoops. Thanks for the correction, I missed our a const. The
Decrypt() function takes a char const*.

rossum
 

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

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top