N
Nick Bishop
I have a problem where I call a method in a C++ class with a pointer
which is a static member in that class. When I use a debugger, I see
the pointer having a certain value, but when I step into the method
(F11), the pointer has a different value and is not pointing at
anything valid.
The small program (complete source below) demonstrates what I am
trying to achieve. The small program works perfectly, but when I
incorporate this logic into a much larger program, I see the pointer
corruption happening. My workaround is that I use a file scope static
pointer declared with the same contents as the class static pointer,
in the style of the commented out workaround in the source code below.
This leaves some problems:
1. I can't reproduce the behaviour in a small program
2. I'm not in a position to put the Big Program source here, and
even if I could, you wouldn't read it
3. The differences between the small program and the Big Program are
a. ... "umm, the size".
b. the Big Program is coded as an older style Windows Service,
which I believe was migrated from Visual C++ ver 6.0
c. the Big Program version of "Nick" has a .DEF file, in debug
mode is generated dynamically, but in release mode is edited by hand,
putting in the mangled names of Nick::OneTwo and Nick:rintTheList
4. There's SOMETHING about the Big Program that is screwing it up,
but what?
My question is what should I check for?
Nick Bishop
email replies ignored. Additional information below.
(Description of environment starts here)
I am using Visual Studio .NET, the original Enterprise Architect
version from 2002 (or rather it is using me).
This is being done on Windows 2000 Professional.
I created the solution (with TheConsole project) as a Win32 project,
and clicked Console Application in the wizard. I then added another
project (Nick) as a DLL project.
I therefore have one solution, and two projects, and a fully expanded
Solution Explorer for the Small Program looks like this:
Solution 'TheConsole' (2 projects)
- Nick
- Source Files
Nick.cpp
stdafx.cpp
- Header Files
Nick.h
stdafx.h
- Resource Files (with no files)
ReadMe.txt
- TheConsole (as startup project)
- Source Files
TheConsole.cpp
stdafx.cpp
- Header Files
stdafx.h
- Resource Files (with no files)
ReadMe.txt
(Source code starts here)
// ----- Nick.h -----------------------------------------------------
#ifndef NICK_H
#define NICK_H
#ifdef NICK_EXPORT
#define EXPORTTESTER_API __declspec(dllexport)
#else
#define EXPORTTESTER_API __declspec(dllimport)
#endif
class EXPORTTESTER_API Nick
{
public:
// This static pointer is intended to be a convenient, commonly used
list-of-strings
// that can be used by callers as a parameter to PrintTheList, but
they still have
// the freedom to supply their own list.
// I do NOT want to use the C++ default argument feature.
static const char* const OneTwo[];
// This is the (non-static) method.
void PrintTheList(const char* const* theList);
};
#endif
// ----- Nick.cpp ---------------------------------------------------
// Nick.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
#define NICK_EXPORT
#include "Nick.h"
#include <iostream>
const char* const Nick::OneTwo[] =
{
"One", "Two", 0
};
void Nick:rintTheList(const char* const* theList)
{
const char* iter;
int i = 0;
for (iter = theList[0]; iter; iter = theList)
{
std::cout << iter << std::endl;
++i;
}
std::cout << "Finished" << std::endl;
}
// ----- TheConsole.cpp ---------------------------------------------
// TheConsole.cpp : Defines the entry point for the console
application.
//
#include "stdafx.h"
#include "..\Nick\Nick.h"
//In the Big Program, the workaround is to declare a local copy of the
pointer.
//static const char* const myOneTwo[] =
// {
// "One", "Two", 0
// };
int _tmain(int argc, _TCHAR* argv[])
{
Nick n;
// Call the method with the "commonly used list"
n.PrintTheList(Nick::OneTwo);
// In the big program, the workaround is to use the local pointer
// n.PrintTheList(myOneTwo);
return 0;
}
// ----- TheConsole.cpp end -----------------------------------------
which is a static member in that class. When I use a debugger, I see
the pointer having a certain value, but when I step into the method
(F11), the pointer has a different value and is not pointing at
anything valid.
The small program (complete source below) demonstrates what I am
trying to achieve. The small program works perfectly, but when I
incorporate this logic into a much larger program, I see the pointer
corruption happening. My workaround is that I use a file scope static
pointer declared with the same contents as the class static pointer,
in the style of the commented out workaround in the source code below.
This leaves some problems:
1. I can't reproduce the behaviour in a small program
2. I'm not in a position to put the Big Program source here, and
even if I could, you wouldn't read it
3. The differences between the small program and the Big Program are
a. ... "umm, the size".
b. the Big Program is coded as an older style Windows Service,
which I believe was migrated from Visual C++ ver 6.0
c. the Big Program version of "Nick" has a .DEF file, in debug
mode is generated dynamically, but in release mode is edited by hand,
putting in the mangled names of Nick::OneTwo and Nick:rintTheList
4. There's SOMETHING about the Big Program that is screwing it up,
but what?
My question is what should I check for?
Nick Bishop
email replies ignored. Additional information below.
(Description of environment starts here)
I am using Visual Studio .NET, the original Enterprise Architect
version from 2002 (or rather it is using me).
This is being done on Windows 2000 Professional.
I created the solution (with TheConsole project) as a Win32 project,
and clicked Console Application in the wizard. I then added another
project (Nick) as a DLL project.
I therefore have one solution, and two projects, and a fully expanded
Solution Explorer for the Small Program looks like this:
Solution 'TheConsole' (2 projects)
- Nick
- Source Files
Nick.cpp
stdafx.cpp
- Header Files
Nick.h
stdafx.h
- Resource Files (with no files)
ReadMe.txt
- TheConsole (as startup project)
- Source Files
TheConsole.cpp
stdafx.cpp
- Header Files
stdafx.h
- Resource Files (with no files)
ReadMe.txt
(Source code starts here)
// ----- Nick.h -----------------------------------------------------
#ifndef NICK_H
#define NICK_H
#ifdef NICK_EXPORT
#define EXPORTTESTER_API __declspec(dllexport)
#else
#define EXPORTTESTER_API __declspec(dllimport)
#endif
class EXPORTTESTER_API Nick
{
public:
// This static pointer is intended to be a convenient, commonly used
list-of-strings
// that can be used by callers as a parameter to PrintTheList, but
they still have
// the freedom to supply their own list.
// I do NOT want to use the C++ default argument feature.
static const char* const OneTwo[];
// This is the (non-static) method.
void PrintTheList(const char* const* theList);
};
#endif
// ----- Nick.cpp ---------------------------------------------------
// Nick.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
#define NICK_EXPORT
#include "Nick.h"
#include <iostream>
const char* const Nick::OneTwo[] =
{
"One", "Two", 0
};
void Nick:rintTheList(const char* const* theList)
{
const char* iter;
int i = 0;
for (iter = theList[0]; iter; iter = theList)
{
std::cout << iter << std::endl;
++i;
}
std::cout << "Finished" << std::endl;
}
// ----- TheConsole.cpp ---------------------------------------------
// TheConsole.cpp : Defines the entry point for the console
application.
//
#include "stdafx.h"
#include "..\Nick\Nick.h"
//In the Big Program, the workaround is to declare a local copy of the
pointer.
//static const char* const myOneTwo[] =
// {
// "One", "Two", 0
// };
int _tmain(int argc, _TCHAR* argv[])
{
Nick n;
// Call the method with the "commonly used list"
n.PrintTheList(Nick::OneTwo);
// In the big program, the workaround is to use the local pointer
// n.PrintTheList(myOneTwo);
return 0;
}
// ----- TheConsole.cpp end -----------------------------------------