C++ MFC: Memory Leak When Creating CString From Char* - c++

I am getting a memory leak when I run try to read from Clipboard.
Sample code:
void SomeFunction()
{
OpenClipboard(nullptr);
HGLOBAL hglb = GetClipboardData(CF_TEXT);
char* ch = static_cast<char*>(GlobalLock(hglb));
CString rawClipboardData(ch);
GlobalUnlock(hglb);
CloseClipboard();
}
It is the middle row above which causes the memory leak according to Visual Studio. This row:
CString rawClipboardData(ch);
If I do not run it, there is no leak reported.
But if I do run it I get the following debug output in visual studio output window:
Detected memory leaks!
Dumping objects ->
f:\dd\vctools\vc7libs\ship\atlmfc\src\strcore.cpp(158) : {75645} normal block at 0x00000000072C89A0, 52 bytes long.
Data: <`x > 60 78 F7 D3 FE 07 00 00 0D 00 00 00 0D 00 00 00
Object dump complete.
Any ideas?
UPDATE: Added OpenClipboard(nullptr) in code above. Also in real code there are nullptr-checks. Just keeping it clean here to reduce amount of guard-clause code.

GlobalLock(hglb) should be a LPTSTR so I would assume that the leak is caused by the cast to char*. For Unicode platforms, TCHAR is defined as synonymous with the WCHAR type.
you should be able to do something like
CString rawClipboardData = GlobalLock(hglb);
If not then
CString rawClipboardData;
LPTSTR lptstr = GlobalLock(hglb);
rawClipboardData = lptstr;
will definitely work

Related

Converting argv[1] from wchar_t** to char** leads to encoding artifacts (Windows)

I have a Unicode Windows application written in C++. I am trying to convert argv[1] from wchar_t* to char* using the standard codec library.
int wmain(int argc, wchar_t **argv) {
using namespace std;
wstring_convert<codecvt_utf8<wchar_t>, wchar_t> converter;
string str = converter.to_bytes(argv[1]);
cout << str << endl;
return 0;
}
It leads to encoding artifacts. I am executing my program with a non-ASCII argument, like so (in PowerShell on CMD):
myprgram.exe "é"
It outputs é instead of é. However, if a hardcode the string in my program by replacing argv[1] with L"é", it works. I should precise that my source is encoded using UTF-8.
What is causing the problem?
EDIT: The reason I'm doing the conversion is not to print the argument passed to the program, but to pass it to some function from a third-party library expecting std::string as argument. Outputting directly argv[1] through std::wcout already works. I analyzed the byte content from both strings and here it is:
argv[1]: e9 00 00 00
L"é": c3 00 a9 00 00 00

Memory leak detected in a very simple program. What to do?

I had a memory leak in my big program, detected by the Visual Studio CRT debug system. I reduced my program to the following, with still shows a memory leak.
#include "stdafx.h"
#include "crtdbg.h"
int main()
{
int tmp = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
_CrtSetDbgFlag(tmp | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
int* k = new int(8);
delete k;
return 0;
}
When I run it in my Visual Studio 2012 system, I see the following:
Detected memory leaks!
Dumping objects ->
{65} normal block at 0x00663008, 4424 bytes long.
Data: <X #f > 58 CF 14 00 90 23 66 00 01 00 00 00 00 00 00 00
{64} normal block at 0x00662390, 4 bytes long.
Data: < > 00 C3 14 00
Object dump complete.
If I remove the allocation and deallocation, the leaks don't appear. If I replace the allocation and deallocation by any standard library feature that uses memory allocation (e.g. std::string k), the leaks appear.
Why do the memory leaks appear? How can I remove them?
I tried debugging my problem by setting _crtBreakAlloc to 64; the system stopped at a place that is supposed to help me (see stack trace below). But I don't know what to do with this info.
> test_it.exe!_heap_alloc_dbg_impl(unsigned int nSize, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp) Line 393 C++
test_it.exe!_nh_malloc_dbg_impl(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp) Line 239 C++
test_it.exe!_nh_malloc_dbg(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine) Line 302 C++
test_it.exe!malloc(unsigned int nSize) Line 56 C++
test_it.exe!_PlatformSpecificMalloc() Unknown
test_it.exe!MemoryLeakWarningPlugin::ignoreAllLeaksInTest(void) Unknown
test_it.exe!operator new(unsigned int) Unknown
test_it.exe!MemoryLeakWarningPlugin::getGlobalDetector(void) Unknown
test_it.exe!std::error_condition::value(void) Unknown
test_it.exe!operator new(unsigned int) Unknown
test_it.exe!main() Line 9 C++
My system is:
Microsoft Visual Studio Professional 2012
Version 11.0.61030.00 Update 4
Visual C++ 2012 04938-004-0034007-02224
Windows 7
Your call stack suggests that there is another memory leak tool being used, besides the Visual C++ runtime functions.
Using google takes me to this link: https://github.com/auser/cpputest/blob/master/src/CppUTest/MemoryLeakWarningPlugin.cpp
So possibly, cppuTest is being applied to your simple project without you being aware of it.
I suggest you create a brand new Win32 Console application, copy and paste your code, and retest. Make sure that the new project has no additional dependencies.
Just tried it with clean VS 2012 installation with Deleaker installed. No leaks shown. And no output from CRT in the final.
What is MemoryLeakWarningPlugin mentioned in the stack trace? Seems it's a part CppUTest (I did Google a bit).
I think either MemoryLeakWarningPlugin leaks itself or it breaks CRT diagnostic system somehow.

Detecting memory leaks in Visual C++ (Windows)

I'm working on a large C++ project under Visual Studio 2010 and think that there are some memory leaks inside. I tried the approach with including crtdbg.h but it does not help much as I don't see where the leaks occured. Defining new has 2 pitfalls: First it needs to be done in every cpp file which is not really an option, and 2nd it breaks with e.g. Boost. Using new(nothrow) or anything that uses boosts "has_new_operator.h" breaks this. [EDIT: It fails to compile as the redefined "new" has no overloads for something like "nothrow" or the "boost magic"] (Unless one defines "new" after all boost headers including headers referencing boost)
Last but not least: I have singletons. They are implemented using subclasses of the singleton template and a static function variable. One of them is a config container where one registers settings (pairs of strings and ints that are than stored in maps) Since the mem leak dump is called before deallocation of the singleton instance I get a massive amount of leaks for all those strings and the singleton itself.
Any way to have only the real leaks shown or make it dump after static object deallocation?
Which free tools can handle this case?
I have used the Visual Leak Detector with quite positive results. It is small and neat, and can be built into your project (assuming you have a running Debug configuration) in a matter of seconds:
https://vld.codeplex.com/
If set-up correctly (which can be done using the installer) then you only have to
#include <vld.h>
in one of your .cpp files for each module - that's it, the header will do the linking for you. You don't have to put it everywhere. Internally the tool uses the CrtDbg, so you have to have a debug build running in order for it to work.
It gives you debugger or text output after each run (if configured using a config file), even when not run through a debugger. It is not the most powerfull tool, but these usually cost some coin ;)
EDIT: There is a possibility to enable the VLD also in non-debug configurations by defining VLD_FORCE_ENABLE before including the header. But the results may be tempered with then.
EDIT: I have tried a fresh installation of VLD. Note that for VS2013 compilers the v2.4rc2 version must be used (or anything greater v2.3). Version v2.3 only works up until VS2010 compilers.
After installation I created a new project and set-up my include- and library-directories to include the respective VLD folders. After that I used the following code to test memleak reports of singletons (note that this code doesn't make sense, it just proves a point):
#include <iostream>
#include <string>
#include <sstream>
#include <map>
// Uncomment this, if you want VLD to work in non-debug configurations
//#define VLD_FORCE_ENABLE
#include <vld.h>
class FooSingleton {
private:
std::map<std::string, std::string*>
_map;
FooSingleton() {
}
public:
static FooSingleton* getInstance(void) {
/* THIS WOULD CAUSE LEAKS TO BE DETECTED
SINCE THE DESTRUCTOR WILL NEVER BE CALLEd
AND THE MAP IS NOT CLEARED.
*/
// FooSingleton* instance = new FooSingleton;
// return instance;
static FooSingleton instance;
return &instance;
}
void addString(const std::string& val) {
_map.insert(std::make_pair(val, new std::string(val)));
}
~FooSingleton(void) {
auto it = _map.begin();
auto ite = _map.end();
for(; it != ite; ++it) {
delete it->second;
}
}
};
int main(int argc, char** argv) {
FooSingleton* fs = FooSingleton::getInstance();
for(int i = 0; i < 100; ++i) {
std::stringstream ss;
ss << i << "nth string.";
fs->addString(ss.str());
}
return 0;
}
With this code, the VLD does not report any leaks because the static auto-variable in getInstance() will be destructed upon exit and the elements in the map will be deleted. This must be done nevertheless, even if it's a singleton, otherwise the leaks will be reported. But in this case:
Visual Leak Detector Version 2.3 installed.
Aggregating duplicate leaks.
Outputting the report to the debugger and to D:\dev\projects\tmp\memleak\memleak\memory_leak_report.txt
No memory leaks detected. Visual Leak Detector is now exiting.
If the code in the getInstance() is changed to the commented version, then the singleton is never cleared up and the following leaks (amongst others) is reported:
---------- Block 11 at 0x008E5928: 52 bytes ----------
Leak Hash: 0x973608A9 Count: 100
Call Stack:
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory (36): memleak.exe!std::_Allocate<std::_Tree_nod<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::alloca + 0x15 bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory (187): memleak.exe!std::allocator<std::_Tree_nod<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::alloca + 0xB bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree (560): memleak.exe!std::_Tree_val<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,s + 0xD bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree (588): memleak.exe!std::_Tree_val<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,s + 0x8 bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree (756): memleak.exe!std::_Tree<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std:: + 0x17 bytes
d:\dev\projects\tmp\memleak\memleak\main.cpp (33): memleak.exe!FooSingleton::addString + 0xA9 bytes
d:\dev\projects\tmp\memleak\memleak\main.cpp (51): memleak.exe!main + 0x37 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (555): memleak.exe!__tmainCRTStartup + 0x19 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): memleak.exe!mainCRTStartup
0x76BF919F (File and line number not available): KERNEL32.DLL!BaseThreadInitThunk + 0xE bytes
0x7739A22B (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x84 bytes
0x7739A201 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x5A bytes
Data:
C0 53 8E 00 30 67 8E 00 C0 53 8E 00 98 58 8E 00 .S..0g.. .S...X..
30 6E 74 68 20 73 74 72 69 6E 67 2E 00 CD CD CD 0nth.str ing.....
0C 00 00 00 0F 00 00 00 CD CD CD CD 48 56 8E 00 ........ ....HV..
01 00 CD CD
You can clearly see the Count: 100 for this block of code, which is correct.
I also edited my vld.ini file in the installation directory to have the following set to be enabled:
AggregateDuplicates = yes
ReportTo = both
These make sure that a) all duplicate leaks are squashed together to one report with a leak-count (as above, otherwise there would be 100 entries) and the other so that a report-file is dumped in the directory of the application.
So for singletons it works fine as long as you use the static auto-variable approach you are using and do your cleanup in the destructor.
EDIT: Also, the instrumentation can be disabled at specific code pieces. If the above code would be modified like this:
void addString(const std::string& val) {
VLDDisable();
_map.insert(std::make_pair(val, new std::string(val)));
VLDEnable();
}
The leaks will never be profiled and not tracked.
You can get memory leaks source from crtdebug. it won't help you with the boost allocations, unless you compile boost (or any library) in the same way, but for the rest, it will show you allocation file and line.
This is how you use properly the crtdebug.h:
in the top of your stdafx.h (or any PCH file) add the following lines:
#ifdef DEBUG
//must define both _CRTDBG_MAP_ALLOC and _CRTDBG_MAP_ALLOC_NEW
#define _CRTDBG_MAP_ALLOC
#define _CRTDBG_MAP_ALLOC_NEW
#include <stdlib.h>
#include <crtdbg.h>
//if you won't use this macro you'll get all new as called from crtdbg.h
#define DEBUG_NEW new( _CLIENT_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#endif
Now in the beginning of your main or winmain or any entry point to your program add the following lines:
//register memory leak check at end of execution:
//(if you use this you won't need to use _CrtDumpMemoryLeaks at the end of your main)
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
//set report mode:
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );
Now here a small test I've made:
After a new console program from VS10 called "test":
My stdafx.h:
#pragma once
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#define _CRTDBG_MAP_ALLOC_NEW
#include <stdlib.h>
#include <crtdbg.h>
#define DEBUG_NEW new( _CLIENT_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#endif
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
and my test.cpp is:
#include "stdafx.h"
void CheckMemoryLeak()
{
char *ptr=new char[100];
int n=900;
sprintf(ptr,"%d",n);
}
int _tmain(int argc, _TCHAR* argv[])
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );
CheckMemoryLeak();
return 0;
}
Output is:
'tests.exe': Loaded 'C:\Users\shr\Documents\Visual Studio 2010\Projects\tests\Debug\tests.exe', Symbols loaded.
'tests.exe': Loaded 'C:\Windows\SysWOW64\ntdll.dll', Cannot find or open the PDB file
'tests.exe': Loaded 'C:\Windows\SysWOW64\kernel32.dll', Cannot find or open the PDB file
'tests.exe': Loaded 'C:\Windows\SysWOW64\KernelBase.dll', Cannot find or open the PDB file
'tests.exe': Loaded 'C:\Windows\SysWOW64\msvcr100d.dll', Symbols loaded.
Detected memory leaks!
Dumping objects ->
c:\users\shr\documents\visual studio 2010\projects\tests\tests\tests.cpp(9) : {97} client block at 0x01003288, subtype 0, 100 bytes long.
Data: <900 > 39 30 30 00 CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
The program '[1600] tests.exe: Native' has exited with code 0 (0x0).

C++ throwing exception causes memory leak

I recently experienced a memory leak issue. I troubleshooted the issue for quite a long time and subsequently found out that throwing an exception (I use my own exception classes) causes this memory leak. The code of throwing the exception is as following:
HINSTANCE lib = LoadLibrary(path.c_str());
if(!lib)
{
DWORD werror = GetLastError();
ostringstream stream;
stream << werror;
string errstring = "Error " + stream.str();
errstring.append(" - " + libraryName);
throw LibraryLoadException(MOD_ERROR_LIB_LOAD, errstring.c_str());
}
The resulting output looks like:
Detected memory leaks!
Dumping objects ->
{351} normal block at 0x0044D208, 32 bytes long.
Data: <Error 126 - note> 45 72 72 6F 72 20 31 32 36 20 2D 20 6E 6F 74 65
{347} normal block at 0x0043BD98, 8 bytes long.
Data: <4 > > 34 F2 3E 00 00 00 00 00
{344} normal block at 0x0043FDE8, 32 bytes long.
Data: <126 > 31 32 36 CD CD CD CD CD CD CD CD CD CD CD CD CD
{302} normal block at 0x004409D8, 8 bytes long.
Data: <4 > > 34 F3 3E 00 00 00 00 00
{301} normal block at 0x0043FAF0, 8 bytes long.
Data: <P > > 50 F3 3E 00 00 00 00 00
Object dump complete.
As seen in the output of the visual studio leak CrtDbg, there are actual values of the objects used in the if block. All these objects including the exception itself (and all its attributes) are allocated on stack, though, so there cannot be a fault of me forgetting to deallocate something on heap.
I empirically tested this and the leak is definitely caused by the objects in the if block (after removing several objects like the string, DWORD and the stream the leaks grow fewer).
Can anyone tell me what am I doing (or what is) wrong over here?
Thank You in advance
As for the comments asking for more detailed code, here is the method causing memory leak:
void ModuleLoader::load(std::string libraryName, std::string type, void(CALLBACK * receiveData)(Message))
{
path = s2ws(libraryName); // conversion to wide string
HINSTANCE lib = LoadLibrary(path.c_str());
if(!lib)
{
DWORD werror = GetLastError();
ostringstream stream;
stream << werror;
string errstring = "Error " + stream.str();
errstring.append(" - " + libraryName);
throw LibraryLoadException(MOD_ERROR_LIB_LOAD, errstring.c_str());
}
DllModule *module = new DllModule(libraryName, lib);
module->setModType(type);
try
{
startModule(module, receiveData);
moduleMap.insert(std::pair<std::string, DllModule *>(type, module));
}
catch (ProbeCoreException e)
{
delete module;
throw e;
}
}
It is a method of a singleton class that loads dynamic modules, defined as following:
class ModuleLoader
{
// Function pointer definitions
typedef void (*StopFuncPointer)();
typedef int (*StartFuncPointer)(void(CALLBACK * receiveData)(Message));
typedef void (*SetDataFunctionPointer)(Message);
private:
std::map<std::string, DllModule *> moduleMap; // map of loaded modules
std::wstring path;
std::wstring s2ws(const std::string &s);
void startModule(DllModule * module, void(CALLBACK * receiveData)(Message));
void stopModule(DllModule * module);
// singleton functions
ModuleLoader() {}; // private constructor
ModuleLoader(ModuleLoader const&);
void operator = (ModuleLoader const&);
public:
void load(std::string libraryName, std::string type, void(CALLBACK * receiveData)(Message));
void unload(std::string libraryType);
void unloadAll();
vector<DllModule> getLoadedModules();
int containsModuleType(string modType);
HINSTANCE getModuleLibraryByType(std::string type);
// singleton getInstance function
static ModuleLoader & getInstance()
{
static ModuleLoader instance;
return instance;
}
};
The s2ws method converts a common string to wide string (i post it just in case):
std::wstring ModuleLoader::s2ws(const std::string& s)
{
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}
I checked many times and deallocating heap objects when the exception is thrown should be carried out at all levels of the application.
Furthermore, if I do remove the DWORD, ostringstream and string objects (allocated on stack), the memory leaks grow fewer...so it HAS to be in connection with these as well. I cannot imagine how removing this part of the code should help heap memory deallocation elsewhere:
DWORD werror = GetLastError();
ostringstream stream;
stream << werror;
string errstring = "Error " + stream.str();
errstring.append(" - " + libraryName);
OK, I managed to reduce the leaks to just two of original 5:
Dumping objects ->
{312} normal block at 0x0045FDC8, 8 bytes long.
Data: <( ( > 28 ED 28 00 00 00 00 00
{311} normal block at 0x0045F810, 8 bytes long.
Data: <D ( > 44 ED 28 00 00 00 00 00
Object dump complete.
I used _CrtSetBreakAlloc(x) function with the x being a number of the leak (e.g. 311 or 312 in the case like above) and found out, where is the unallocated memory allocated. It is really difficult to believe it, but the allocations really occured on these lines:
string errstring = "Error " + stream.str();
and
errstring.append(" - " + libraryName);
I removed the leaks by making the string and stream dynamically allocated on heap, then creating the exception and storing it in a temporary variable, subsequently deallocating the string and stream variables and finally throwing the exception itself:
DWORD werror = GetLastError();
ostringstream *stream = new ostringstream();
*stream << werror;
string *errstring = new string("Error ");
errstring->append(stream->str());
errstring->append(" - ");
errstring->append(libraryName);
ProbeCoreException e = LibraryLoadException(MOD_ERROR_LIB_LOAD,
errstring->c_str());
delete errstring;
delete stream;
throw e;
The last two allocations occur (once again unbelievably) during passing string parameters to the "load" function itself:
loader.load("notexisting.dll", "TEST", &callbackFunction);
I was contemplating about the leaks occuring due to the class being a singleton, the class was created according to leak-proof singleton rules, though, mentioned here:
C++ Singleton design pattern
It seems that the only chance how to get rid of the resting leaks is to pass string pointers even as parameters and then dealloc them explicitly...

C++ ifstream/fstream corrupting data

I'm new to C++ and I've to do an assignment for school.
I need to copy a binary* file without using api calls or system integrated commands. At school we use a windows machine.
I've searched around a bit, and I found out that the best way to copy data without using any api's is to use iostream (ifstream/fstream)
Here's the code I'm using:
int Open(string Name){
int length;
char * buffer;
ifstream is;
fstream out;
FILE* pFile;
is.open (Name.c_str(), ios::binary );
// get length of file:
is.seekg (0, ios::end);
length = is.tellg();
is.seekg (0, ios::beg);
// allocate memory:
buffer = new char [length];
// read data as a block:
is.read (buffer,length);
is.close();
pFile = fopen ( "out.exe" , "w" );
fclose(pFile);
out.open("out.exe", ios::binary);
out.write( buffer, length);
out.close();
delete[] buffer;
return 0;
}
out.exe isnt working properly, and after looking at it in winhex.exe
I see that the data has been modefied, while I'm not doing anything with it
Can anyone help me?
*the file is a simple hello world program, it messageboxes "hello world"
EDIT:
Sorry for my unresponsiveness, It was sleeping.
Anyways, I've opened both (the result and the original) programs inside an hex editor.
It seems that with everything I try this line:
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
00000200 4C 00 00 00 00 30 00 00 00 02 00 00 00 0D 0A 00 L 0
Changes into this:
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
00000200 4C 00 00 00 00 30 00 00 00 02 00 00 00 0A 00 00 L 0
As you can or cannot see somehow during the reading or writing process a byte is being removed (or added, that sometimes happens as well)
Passing only ios_base::binary to fstream's ctor is not specified (in and/or out must be supplied too).
To avoid that, you could use ofstream (note the exra 'o') for out instead of fstream. As a bonus, this would avoid the need to first fopen with the "w" flag since ofstream's ctor creates the file by default.
is.read(buffer, length) is not guaranteed to read length bytes.
I forget if the same is true for out.write or not.
Lets make that a bit neater:
// Pass strings by const reference (just good habit)
// But may also save a copy. And it indicates that the function should
// not be messing with the name!
int Open(std::string const& Name, std::string const& out)
{
// Declare variables as close to use as possable.
// It is very C-Like to declare all the variables at the
// head of a function.
// Use the constructor to open the file.
std::ifstream is(Name.c_str(), ios::binary);
if (!is) // Failed to open
{ return -1;
}
// get length of file:
is.seekg (0, ios::end);
std::size_t length = is.tellg(); // Use the correct type. int is not correct
is.seekg (0, ios::beg);
// allocate memory:
// Using new/delete is risky. It makes the code not exception safe.
// Also because you have to manually tidy up the buffer you can not
// escape early. By using RAII the cleanup becomes automative and there
// is no need to track resources that need to be tidied.
//
// Look up the concept of RAII it makes C++ lfe so much easier.
// std::vector implements the new/delete internally using RAII
std::vector<char> buffer(length);
std::size_t read = 0;
do
{
// read does not gurantee that it will read everything asked for.
// so you need to do int a loop if you want to read the whole thing
// into a buffer.
is.read(&buffer[read], length - read);
std::size_t amount = is.gcount();
if (amount == 0)
{ return -2; // Something went wrong and it failed to read.
}
read += amount;
} while(length != read);
fstream out(out.c_str(), ios::binary );
if (!out)
{ return -3; // you may want to test this before spending all the time reading
}
// Probably need to loop like we did for read.
out.write( &buffer[0], length);
return 0;
}
Generally, files end in a newline. That 0d0a ("\r\n") might not be a readable part of the source file. Windows usually uses "\r\n" for newline, while UNIX uses just "\n". For some reason, when it writes a new file, it's using just 0a for the final newline. It might be interesting to see what happens if you read in and copy the file you wrote the first time.
The short answer is, this is just the kind of problem that crops up when you use a Windows system. :D
To hack it, you could always unconditionally write an extra "\r" as the last thing you output.
I think that
ifstream src(source.c_str(), ios::binary);
ofstream dest(destination.c_str(), ios::binary | ios::trunc);
dest << src.rdbuf();
src.close();
dest.close();
would do the trick.