nothing
nothing

Reputation: 19

C++ Garbage at the end of file

I have a problem and I dont know how to solve it. The issue is:

char * ary = new Char[];

ifstream fle;
fle.open(1.txt, ios_base::binary);
fle.seekg(fle.end);
long count = fle.tellg();
fle.seek(fle.beg);

here is the problem: File 1.txt contains: Hello world!.

when I execute:

ary = new char(count);
fle.read(ary, count);

the ary filled like this: Hello world! @T#^@$@FF(garbage)

The file is ookay nothing inside it only what is above.

Platform: Win 7, VS 2012

Any idea how to solve this issue. (Solved)

(Problem 2) Now I am facing another problem, the fle.read sometimes read more than the size i gave. For Example if i passed like fle.read(buffer, 1000) it ends in some cases (strlen(buffer) = 1500. How can i solve this?

Regards,

Upvotes: 0

Views: 3724

Answers (7)

Ole Dittmann
Ole Dittmann

Reputation: 1774

Try this

ary = new char[count + 1];
fle.read(ary,count);
ary[count] = '\0';

The terminating null character was missing - its not in the file, you have to add it afterwards

Upvotes: 0

Maxime Chéramy
Maxime Chéramy

Reputation: 18821

I think your problem is not that your array contains garbage, but that you forgot to put the null-terminator character at the end and your print statement doesn't know when to stop.

Also, you wrote new char(count) instead of new char[count]. In the first case, you only instantiate one char with value count while in the second case you create a buffer of count characters.

Try this:

ary = new char[count+1];
fle.read(ary, count);
ary[count] = '\0';

Upvotes: 3

James Kanze
James Kanze

Reputation: 153899

Well, the most obvious problem is that you are allocating using new char(count), which allocates a single char, initialized with count. What you were probably trying to do would be new char[count]. What you really need is:

std::vector<char> arr( count );
fle.read( &arr[0], count );

Or maybe count + 1 in the allocation, if you want a trailing '\0' in the buffer.

EDIT:

Since you're still having problems: fle.read will never read more than requested. What does fle.gcount() return after the read?

If you do:

std::vector<char> arr( count );
fle.read( &arr[0], count );
arr.resize( fle.gcount() );

you should have a vector with exactly the number of char that you have read. If you want them as a string, you can construct one from arr.begin(), arr.end(), or even use std::string instead of std::vector<char> to begin with.

If you need a '\0' terminated string (for interface with legacy software), then just create your vector with a size of count + 1, instead of count, and &arr[0] will be your '\0' string.

Do not try to use new char[count] here. It's very difficult to do so correctly. (For example, it will require a try block and a catch.)

Upvotes: 2

Roman Zavalov
Roman Zavalov

Reputation: 585

Most of the other answers miss a very important point: When you do ary = new char(count); you allocate A SINGLE CHARACTER initialized with a symbol with ASCII code count. You should write this: ary = new char[count + 1];

Upvotes: 2

Laurent LA RIZZA
Laurent LA RIZZA

Reputation: 2965

You're reading count characters for a file, you have to allocate one extra character to provide for the string terminator (\0).

ary = new char[count + 1];
ary[count] = '\0';

Upvotes: 0

Philipp
Philipp

Reputation: 69663

char[]-strings in C are usually null-terminated. They are one byte longer than necessary, and the last byte is set to 0x00. That's necessary because C has no way to tell the length of an array.

When you read binary data from a file, no terminating null-character is read into the string. That means a function like printf which operates on char-arrays of unknown length will output the array and any data which happens to come after it in memory until it encounters a null-character.

Solution: allocate the char[]-buffer one byte longer than the length of the data and set the last byte to 0 manually.

Better solution: Don't use C-style char-arrays. Do it the object-oriented way and use the class std::string to represent strings.

Upvotes: 5

David Heffernan
David Heffernan

Reputation: 612794

We have to guess a little here, but most likely this comes down to an issue with your debugging. The buffer is filled correctly, but you inspect its contents incorrectly.

Now, ary is declared as char* and I suspect that when you attempt to inspect the contents of ary you use some printing method that expects a null-terminated array. But you did not null-terminate the array. And so you have a buffer overrun.

If you had only printed count characters, then you would not have overrun. Nor would you if you had null-terminated the array, not forgetting to allocate an extra character for the null terminator.

Instead of using raw arrays and new, it would make much more sense to read the buffer into std::string. You should be trying to avoid null-terminated strings as much as possible. You use those when performing interop with non-C++ libraries.

Upvotes: 1

Related Questions