Been stuck on this all day.The data in statsStruct becomes corrupt very first second the program starts in main at line 1. I do not know why when ever I try to declare statsStruct as global it becomes this way.
EDIT: This does compile just the values are all messed up in statsstruct, text is corrupted and value is 323232
extern attributes statsStruct[];
statsStruct is extern in header file for multiple cpp but Iv deleted all source code till just statsSTruct remains but I cannot get it to be global. When i declare it inside a function it works with good values but I need it global across multiple files and have it share same value.
// tess.cpp : main project file.
#include "stdafx.h"
#include "Form1.h"
#include "test.h"
using namespace tess;
struct attributes{
std::string stat;
int amount;
};
attributes statsStruct[] = {{"Acc",0},
{"Cri",0},
{"Cr",0},
{"Crit",0},
{"Cr",0},
{"Ev",0},
{"An",0}};
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
// Enabling Windows XP visual effects before any controls are created
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
// Create the main window and run it
Application::Run(gcnew Form1());
return 0;
}
I think I got a repro for this, rather by accident. It is caused by a compiler setting in your project. To fix it, right-click your project in the Solution Explorer window, Properties, General. Change the Common Language Runtime support setting from /clr:pure to /clr
I need to wave my hands a bit at the explanation. With /clr:pure in effect, the compiler is only allowed to generate pure IL and no machine code. Problem is, the CLR does not support global variables. The compiler has to pull a few stunts to emulate your attributes[] array, an unmanaged array, and get it initialized properly. This appears to be enough to confuse the debugger, it takes you to the shim for "statsArray" instead of the actual statsArray data. You'll indeed see garbage in the array elements. An extra pointer dereference is required, and then some, the debugger forgets to do this.
Always compile with /clr in effect if you use unmanaged declarations.
Related
I broke my Visual Studio project (2015, C++) into three pieces:
The main application in a static library
The executable which just has a main function
Unit tests which use the static .lib file so that they can import the required classes and do the unit tests on them.
Before I split it into a lib/exe/tests, the main application was just a standalone executable, and it worked perfectly fine.
Now I can't run the executable with only the main function, nor the unit tests as a certain pointer is always null. The only main difference is that I'm using a raw pointer in this example, but I was using a unique_ptr in my code (currently however I switched to the raw pointer just to make sure this following example is as accurate as possible and it didn't magically compile/run properly with the raw pointer).
The code looks very similar to the following (the extra code has been removed):
// console.hpp
extern Console *console;
The implementation cpp file (only of what is needed):
// console.cpp
Console *console = new Console();
Now in some unrelated function, this code fails due to the console pointer being a nullptr:
// some_other_file.cpp
#include "console.hpp"
// Inside some function...
console->doSomething(); // console is NULL
Again, the code I have worked perfectly fine when it was in one project. Regardless, it all compiles fine with no linking errors even though it has been broken into 3 pieces, but now that pointer is always null.
As a last interesting note, the non-pointer variables that are global and extern do work. Is this something limited to pointers/unique_ptrs?
Is this something fixable by a singleton pattern?
The clue is in this comment: "it appears other code is getting called before the main function that don't let the global variable get initialized."
The code referencing console is probably running as part of the initialization of another global and, in this case, is happening before the initialization of console. You have to be very careful to be sure that you're not depending on the order of the global initializers. You were probably getting lucky before you split the program, and now your luck has run out.
The easiest way to fix it is to use a singleton pattern. Instead of having other parts of the program directly reference the pointer, you have them call a function that returns the pointer, and that function will initialize it the first time. This ensures that it's initialized before it's used.
Here's a common pattern for it:
Console *GetConsole() {
static Console *console = new Console();
return console;
}
Now console is no longer a global variable. Everything that wants to access the console calls GetConsole instead.
The function-local static variable will be initialized the first time the function is called, and after that it just returns the value. If you have multiple threads and an older compiler, you have to do more work to protect against a possible race condition. Modern compilers should do the initialization in a thread-safe way.
I have been writing Java for a long time using Eclipse, now trying to switch to C++ in Visual Studio. From Eclipse/Java I know such auto-complete features: I write
bar = Foo.valueOf(x);
bar.doSomething(y, z);
and Eclipse offers me both to import whatever Foo I might mean, and declare bar as local variable, field, or parameter. Or create the function doSomething() with the appropriate signature, auto-adding missing imports to Foo. I am missing a corresponding feature on Visual Studio 2015, which does for example
add the corresponding #include and #pragma comment(lib, statements,
add these statements in a clear order, so that they work as expected (something like organize imports),
add namespace statements
declare variables, fields, and parameters on click/keypress
create function bodies, adding the corresponding foreward declarations to the respective header files, adding missing includes required by the declaration
…
The only things that I found so far is the “add class” dialog. When writing an unknown function name, right clicking and choosing “quick actions and refactorings” → Create declaration / definition, a window opens with the text
int main(int argc, char * argv[]);
but it does not create a definition for that function.
Are there some better “save me typing work” functions available in Visual Studio 15, and if yes, how can I benefit from them? Is there another way I could go, such as writing the C++ program (Windows API) in an other IDE (are there any for Winapi C++ which do better?)
Resharper by JetBrains does what you are asking for more or less. It will notice an error in your code, whether it being that something wasn't fully initialized, or something that you needed to include, or a host of other things.
It is not free though, but you can try it on a 30 day trial.
I don't know of an IDE that supports winapi functions like you're asking though. I think you'll just have to pick your favorite IDE and get used to it.
C++ class constructor can be inlined or not be inlined. However, I found a strange situation where only inline class constructor can avoid Visual Studio memory crash. The example is as follows:
dll.h
class _declspec(dllexport) Image
{
public:
Image();
virtual ~Image();
};
class _declspec(dllexport) Testimage:public Image
{
public:
Testimage();
virtual ~Testimage();
};
typedef std::auto_ptr<Testimage> TestimagePtr;
dll.cpp
#include "dll.h"
#include <assert.h>
Image::~Image()
{
std::cout<<"Image is being deleted."<<std::endl;
}
Image::Image()
{
}
Testimage::Testimage()
{
}
Testimage::~Testimage()
{
std::cout<<"Geoimage is being deleted."<<std::endl;
}
The dll library is compiled as a dynamic library, and it is statically linked to the C++ runtime library (Multi-threaded Debug (/MTd)). The executable program that runs the library is as follows:
int main()
{
TestimagePtr my_img(new Testimage());
return 0;
}
The executable program will invoke the dll library and it also statically links the runtime library. The problem I have is that when running the executable program the following error message appears:
However, when the class constructor in dll is inlined as the following codes show:
class _declspec(dllexport) Image
{
public:
Image();
virtual ~Image();
};
class _declspec(dllexport) Testimage:public Image
{
public:
Testimage()
{
}
virtual ~Testimage();
};
The crash will disappear. Could someone explain the reason behind? Thanks! By the way, I am using VC2010.
EDIT: The following situation also trigger the same crash
.
Situation 1
int main()
{
//TestimagePtr my_img(new Testimage());
Testimage *p_img;
p_img = new Testimage();
delete p_img;
return 0;
}
it is statically linked to the C++ runtime library (Multi-threaded Debug (/MTd)
This is a very problematic scenario in versions of Visual Studio prior to VS2012. The issue is that you have more than one version of the CRT loaded in your process. One used by your EXE, another used by the DLL. This can cause many subtle problems, and not so subtle problems like this crash.
The CRT has global state, stuff like errno and strtok() cannot work properly when that global state is updated by one copy of the CRT and read back by another copy. Relevant to your crash, a hidden global state variable is the heap that the CRT uses to allocate memory from. Functions like malloc() and ::operator new use that heap.
This goes wrong when objects are allocated by one copy of the CRT and released by another. The pointer that's passed to free() or ::operator delete belongs to the wrong heap. What happens next depends on your operating system. A silent memory leak in XP. In Vista and up, you program runs with the debug version of the memory manager enabled. Which triggers a breakpoint when you have a debugger attached to your process to tell you that there's a problem with the pointer. The dialog in your screenshot is the result. It isn't otherwise very clear to me how inlining the constructor could make a difference, the fundamental issue however is that your code invokes undefined behavior. Which has a knack for producing random outcomes.
There are two approaches available to solve this problem. The first one is the simple one, just build both your EXE and your DLL project with the /MD compile option instead. This selects the DLL version of the CRT. It is now shared by both modules and you'll only have a single copy of the CRT in your process. So there is no longer a problem with having one module allocating and another module releasing memory, the same heap is used.
This will work fine to solve your problem but can still become an issue later. A DLL tends to live a life of its own and may some day be used by another EXE that was built with a different version of the CRT. The CRT will now again not be shared since they'll use different versions of the DLL, invoking the exact same failure mode you are seeing today.
The only way to guarantee that this cannot happen is to design your DLL interface carefully. And ensure that there will never be a case where the DLL allocates memory that the client code needs to release. That requires giving up on a lot of C++ goodies. You for example can never write a function that returns a C++ object, like std::string. And you can never allow an exception to cross the module boundary. You are basically down to a C-style interface. Note how COM addresses this problem by using interface-based programming techniques and a class factory plus reference counting to solve the memory management problem.
VS2012 has a counter-measure against this problem, it has a CRT version that allocates from the default process heap. Which solves this particular problem, not otherwise a workaround for the global state issue for other runtime functions. And adds some new problems, a DLL compiled with /MT that gets unloaded that doesn't release all of its allocations now causes an unpluggable leak for example.
This is an ugly problem in C++, the language fundamentally misses an ABI specification that addresses problems like this. The notion of modules is entirely missing from the language specification. Being worked on today but not yet completed. Not simple to do, it is solved in other languages like Java and the .NET languages by specifying a virtual machine, providing a runtime environment where memory management is centralized. Not the kind of runtime environment that excites C++ programmers.
I tried to reproduce your problem in VC2010 and it doesn't crash. It works with a constructor inline or not. Your problem is probably not in what you write here.
Your project is too hard to open as it seams to have its file pathes set in absolute, probably because generated with CMake. (So the files are not found by the compiler).
The problem I see in your code is that you declare the exported classes with _declspec(dllexport) directly written.
You should have a #Define to do this, and the value should be _declspec(dllimport) when read from the exe compilation. Maybe the problem comes from that.
I have a C++/CLI project using OpenCV. I compiled this version of OpenCV in VS 2010 myself and I can use it in unmanaged projects without an issue — the trouble started when I tried to use it in a managed one.
The function of interest is cv::imread(std::string&, int). Simply calling it from a managed module did not work at all, producing <invalid pointer> on the receiving end. I was sort of expecting it. After all, managed code has its own std::string implementation.
Things got a little more interesting when I created a separate C++ file, removed CLI support from its module, and placed my code in it. Now, imread was getting a valid pointer, but its contents were scrambled. Apparently, the string I was passing it contained the string pointer offset by 4 bytes, but it expected it to be at the 0 offset.
The unmanaged module is using the same CRT DLL as OpenCV and has all options set to the values appropriate for normal OpenCV use. Why would it have a different string layout? I am lost.
Sample code:
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <string>
using namespace cv;
using namespace std;
void Run()
{
string path("C:\\Users\\Don Reba\\Pictures\\Merlin 1D.jpg");
Mat image(imread(path, CV_LOAD_IMAGE_GRAYSCALE));
imwrite("image.jpg", image);
}
Answering the question in the title: no, you can't directly marshal std::string from managed to unmanaged code. See answers to another SO question on the reasons. Main reason is that std::string is a template and not a "real" type.
Basically, you need to write a small unmanaged module which provides simple wrappers for the openCV functions, getting rid of STL types. With your example function, it can be as simple as that:
declspec(__dllexport) imread(char* c, int i) {
string s = c;
cv::imread(s, i);
}
As for the problem with the string offset... Try creating a separate project, with "Unmanaged" type from the beginning. Switching the project to managed and back can produce a mess with project settings, having unpredictable consequences - at least, I've hit such pits twice...
You shouldn't (can't) pass a std::string& between different modules (DLLs) unless you are sure that all your modules were compiled the same way (release vs. debug etc).
For example: if you compile one DLL in release and another as debug - then the memory layout of std::string is likely to be different.
Other compiler settings may influence the memory layout as well.
Try this - compile the code below as release vs. debug and run it.
In debug you get 32 in relase 28.
#include <iostream>
#include <string>
int main()
{
std::cout << "sizeof(std::string) : " << sizeof(std::string) << std::endl;
return 0;
}
I suggest not to cross module boundaries using std::string.
Short answer: Yes, you can pass a STL string to a native C++ DLL from a C++/CLI app, if you use the same compiler settings for the DLL and the C++/CLI app.
Code:
#include <msclr/marshal_cppstd.h> // header for marshal utilities
...
String^ path = "C:\\Users\\Don Reba\\Pictures\\Merlin 1D.jpg"; // Managed string
std::string s = msclr::interop::marshal_as<std::string>(path); // To stl string
cv::imread(s, CV_LOAD_IMAGE_GRAYSCALE);
See this page for more details: http://msdn.microsoft.com/en-us/library/bb384865.aspx
The problem is that Visual Studio 2010 uses different toolsets for C++ and C++/CLI projects by default. This is why STL classes have different layouts despite identical settings. To fix the problem, make sure that Configuration Properties / General / Platform Toolset is set to v100 in the C++/CLI project.
Whenever I exit my program it gives me this exception "0xC0000022: A process has requested access to an object, but has not been granted those access rights."
It breaks right at the end of a function called _lock_file in _file.c.
After trying to narrow down what the cause of the problem is I found out that it does not crash if I remove all fclose() function calls in my program then cleaning and rebuilding my program. Even if the function itself is never called it will still crash. Obviously this solution is not ideal.
When I tried to use fstream instead it produced a similar crash at the start of the program.
It's also worth mentioning that my program uses SDL.
Edit: Someone requested a minimal example and this is what I cam up with.
main.cpp
#include <stdlib.h>
#include <SDL.h>
/*...*/
#pragma comment(lib, "SDL.lib")
#pragma comment(lib, "SDLmain.lib")
/*...*/
int main( int argc, char **argv)
{
if(false)
fclose(NULL);
return 0;
}
draw.cpp
/*...*/
If I run this it will crash on exit just like I mentioned above. And yes the draw.cpp is completely commented out, but if I remove it from the project the program will run fine. All other files were removed from the project.
Edit2: In response to karlphillip I decided to double check if it is actually running and it seems that it is actually crashing at the start with this example.
Also it is a Win32 project.
Having a crash on exit usually means that the heap is corrupted during program execution. Try using a memory checker to find where. Try using _CrtDumpMemoryLeaks()
Are you using the same runtime library (Debug DLL, Debug, Release DLL, Release, etc.) for your main program as was used to build the SDL library? That can often (but not always) cause odd problems, and would be my first port of call when getting this sort of odd behaviour at runtime.
(If you get an LNK4098 warning when building, this is what it is trying to tell you, and you really need to fix it properly; the "solution" the text of the warning suggests is anything but.)
Another option is memory corruption. Consider running a debug build, and calling the following on startup:
_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)|_CRTDBG_CHECK_ALWAYS_DF);
This activates more thorough heap checking. (You might have to go and make a cup of tea when your program runs with this switched on, if it allocates lots of stuff while it's running.) If then "crashes" in one of the memory allocation functions -- it's actually an assert, you can't always tell though -- then at some point between that call, and the previous call to a memory management function, something has overwritten some memory it should not have. And you can take it from there, to find out what.
-Edit: "_CRTDBG_REPORT_FLAG_DF", was probably intended to be "_CRTDBG_REPORT_FLAG".
Crashing on exit can also be caused by static variables destructing and accessing objects that have already been cleaned up.
Check you static objects and ensure their destructors are not causing the crash.
How do you know your application is being executed in the first place? Add a debug right after main() is called:
#include <stdlib.h>
#include <SDL.h>
/*...*/
#pragma comment(lib, "SDL.lib")
#pragma comment(lib, "SDLmain.lib")
/*...*/
int main( int argc, char **argv)
{
printf("dbg1\n");
if(false)
fclose(NULL);
printf("dbg2\n");
return 0;
}
What kind of project are you creating? Console, Win32 or something else?
I find this post very interesting.