Create a function with unique function pointer in runtime - c++

When calling WinAPI functions that take callbacks as arguments, there's usually a special parameter to pass some arbitrary data to the callback. In case there's no such thing (e.g. SetWinEventHook) the only way we can understand which of the API calls resulted in the call of the given callback is to have distinct callbacks. When we know all the cases in which the given API is called at compile-time, we can always create a class template with static method and instantiate it with different template arguments in different call sides. That's a hell of a work, and I don't like doing so.
How do I create callback functions at runtime so that they have different function pointers?
I saw a solution (sorry, in Russian) with runtime assembly generation, but it wasn't portable across x86/x64 archtectures.

You can use the closure API of libffi. It allows you to create trampolines each with a different address. I implemented a wrapping class here, though that's not finished yet (only supports int arguments and return type, you can specialize detail::type to support more than just int). A more heavyweight alternative is LLVM, though if you're dealing only with C types, libffi will do the job fine.

I've come up with this solution which should be portable (but I haven't tested it):
#define ID_PATTERN 0x11223344
#define SIZE_OF_BLUEPRINT 128 // needs to be adopted if uniqueCallbackBlueprint is complex...
typedef int (__cdecl * UNIQUE_CALLBACK)(int arg);
/* blueprint for unique callback function */
int uniqueCallbackBlueprint(int arg)
{
int id = ID_PATTERN;
printf("%x: Hello unique callback (arg=%d)...\n", id, arg);
return (id);
}
/* create a new unique callback */
UNIQUE_CALLBACK createUniqueCallback(int id)
{
UNIQUE_CALLBACK result = NULL;
char *pUniqueCallback;
char *pFunction;
int pattern = ID_PATTERN;
char *pPattern;
char *startOfId;
int i;
int patterns = 0;
pUniqueCallback = malloc(SIZE_OF_BLUEPRINT);
if (pUniqueCallback != NULL)
{
pFunction = (char *)uniqueCallbackBlueprint;
#if defined(_DEBUG)
pFunction += 0x256; // variable offset depending on debug information????
#endif /* _DEBUG */
memcpy(pUniqueCallback, pFunction, SIZE_OF_BLUEPRINT);
result = (UNIQUE_CALLBACK)pUniqueCallback;
/* replace ID_PATTERN with requested id */
pPattern = (char *)&pattern;
startOfId = NULL;
for (i = 0; i < SIZE_OF_BLUEPRINT; i++)
{
if (pUniqueCallback[i] == *pPattern)
{
if (pPattern == (char *)&pattern)
startOfId = &(pUniqueCallback[i]);
if (pPattern == ((char *)&pattern) + sizeof(int) - 1)
{
pPattern = (char *)&id;
for (i = 0; i < sizeof(int); i++)
{
*startOfId++ = *pPattern++;
}
patterns++;
break;
}
pPattern++;
}
else
{
pPattern = (char *)&pattern;
startOfId = NULL;
}
}
printf("%d pattern(s) replaced\n", patterns);
if (patterns == 0)
{
free(pUniqueCallback);
result = NULL;
}
}
return (result);
}
Usage is as follows:
int main(void)
{
UNIQUE_CALLBACK callback;
int id;
int i;
id = uniqueCallbackBlueprint(5);
printf(" -> id = %x\n", id);
callback = createUniqueCallback(0x4711);
if (callback != NULL)
{
id = callback(25);
printf(" -> id = %x\n", id);
}
id = uniqueCallbackBlueprint(15);
printf(" -> id = %x\n", id);
getch();
return (0);
}
I've noted an interresting behavior if compiling with debug information (Visual Studio). The address obtained by pFunction = (char *)uniqueCallbackBlueprint; is off by a variable number of bytes. The difference can be obtained using the debugger which displays the correct address. This offset changes from build to build and I assume it has something to do with the debug information? This is no problem for the release build. So maybe this should be put into a library which is build as "release".
Another thing to consider whould be byte alignment of pUniqueCallback which may be an issue. But an alignment of the beginning of the function to 64bit boundaries is not hard to add to this code.
Within pUniqueCallback you can implement anything you want (note to update SIZE_OF_BLUEPRINT so you don't miss the tail of your function). The function is compiled and the generated code is re-used during runtime. The initial value of id is replaced when creating the unique function so the blueprint function can process it.

Related

per thread c++ guard to prevent re-entrant function calls

I've got function that call the registry that can fail and print the failure reason.
This function can also be called directly or indirectly from the context of a dedicated built-in printing function, and I wish to avoid printing the reason in this case to avoid endless recursion.
I can use thread_local to define per thread flag to avoid calling the print function from this function, but I guess it's rather widespread problem, so I'm looking for std implementation for this guard or any other well debugged code.
Here's an example that just made to express the problem.
Each print function comes with log level, and it's being compared with the current log level threshold that reside in registry. if lower than threshold, the function returns without print. However, in order to get the threshold, additional print can be made, so I wanted to create a guard that will prevent the print from getPrintLevelFromRegistry if it's called from print
int getPrintLevelFromRegistry() {
int value = 0;
DWORD res = RegGetValueW("//Software//...//logLevel" , &value);
if (res != ERROR_SUCCESS) {
print("couldn't find registry key");
return 0;
}
return value;
}
void print(const char * text, int printLoglevel) {
if (printLogLevel < getPrintLevelFromRegistry()) {
return;
}
// do the print itself
...
}
Thanks !
The root of the problem is that you are attempting to have your logging code log itself. Rather than some complicated guard, consider the fact that you really don't need to log a registry read. Just have it return a default value and just log the error to the console.
int getPrintLevelFromRegistry() {
int value = 0;
DWORD res = RegGetValueW("//Software//...//logLevel" , &value);
if (res != ERROR_SUCCESS) {
OutputDebugStringA("getPrintLevelFromRegistry: Can't read from registry\r\n");
}
return value;
}
Further, it's OK to read from the registry on each log statement, but it's redundant and unnecessary.
Better:
int getPrintLevelFromRegistry() {
static std::atomic<int> cachedValue(-1);
int value = cachedValue;
if (value == -1) {
DWORD res = RegGetValueW("//Software//...//logLevel" , &value);
if (res == ERROR_SUCCESS) {
cachedValue = value;
}
}
return value;
}

is there an way to ignore signals signature?

I'm trying to connect some widgets with the same user_function callback. In some cases, the signal has diferent signatures.
Searching i found gtk_signal_connect_full, I think.
My Code for example:
int MyObject::connect()
{
callback_object ....
// Create the callback
int ret = g_signal_connect(instance, "clicked", G_CALLBACK (connect_callback), callback_object);
int ret = g_signal_connect(instance, "button-release-event", G_CALLBACK (connect_callback), callback_object);
// Return handler id
return ret;
}
void MyObject::connect_callback(GObject *passedInstance, gpointer param1, gpointer param2)
{
// Return to st_callback
struct st_callback *callback_object = (struct st_callback *) param2;
if(sizeof(param1) == 0) {
callback_object = (struct st_callback *) param1;
}
}
Can i "abstract" user_function like that? and if I can, How to get extra parameters like GdkEvent or GdkEventButton, or gchar, ...
EDIT
- This question is a GTK+ issue, because in the first g_signal_connect, param1 is my struct. I'ts ok, I know my struct to cast back. In the second g_signal_connect, param1 is a GdkEventButton. It's OK too, becouse I know it's a GdkEventButton to cast back. BUT, how to do this, if I dont know param1 is my struct, if its a GdkEvent, GdkEventButton, gchar, or all others possibilities of sinal signatures?
EDIT 2
- I have found this info on Closures doc
Closures allow the callee to get the types of the callback parameters, which means that language bindings don't have to write individual glue for each callback type.
This seen perfect for what i'm looking for, but I don't found nothing more that it
EDIT 3
With ebassi ideia about, g_signal_query is what I need. I do this for abstract:
1 - query the params of signal with g_signal_query, set into my structure to pass with callback user_data
2 - connect with g_cclosure_new_swap and g_signal_connect_closure, this set gpointer user_data as first param
3 - created callback like this: connect_callback(gpointer user_data, ...), with variable parameter list
4 - inside callback, get back my struct with custom + g_signal_query result
5 - loop into param_types of GSignalQuery, verifying each fundamental types
6 - get va_arg with correct type
Complete code for call the callback
// Create gpoint param
struct st_callback *callback_object = (struct st_callback *)malloc(sizeof(struct st_callback));
memset(callback_object, 0, sizeof(struct st_callback));
callback_object->callback_name = callback_name;
callback_object->callback_params = callback_params;
// Get params of signal
GSignalQuery signal_info;
g_signal_query(g_signal_lookup (callback_signal, G_OBJECT_TYPE (instance)), &signal_info);
// Save
callback_object->signal_id = signal_info.signal_id;
callback_object->signal_name = signal_info.signal_name;
callback_object->itype = signal_info.itype;
callback_object->signal_flags = signal_info.signal_flags;
callback_object->return_type = signal_info.return_type;
callback_object->n_params = signal_info.n_params;
callback_object->param_types = signal_info.param_types;
GClosure *closure;
closure = g_cclosure_new_swap (G_CALLBACK (connect_callback), callback_object, NULL);
int ret = g_signal_connect_closure (instance, callback_event, closure, TRUE);
And the callback
static bool connect_callback(gpointer user_data, ...)
{
// Return to st_callback
struct st_callback *callback_object = (struct st_callback *) user_data;
// get parameters count
int param_count = callback_object->n_params;
va_list ap;
va_start(ap, param_count);
// loop paramters
for (int i=0; i<param_count; i++) {
switch (G_TYPE_FUNDAMENTAL(callback_object->param_types[i])) {
case G_TYPE_CHAR:
break;
case G_TYPE_UCHAR:
break;
case G_TYPE_STRING:
{
char *path = va_arg(ap, char *);
break;
}
case G_TYPE_OBJECT:
break;
case G_TYPE_POINTER:
break;
case G_TYPE_INTERFACE:
break;
case G_TYPE_PARAM:
break;
case G_TYPE_BOXED:
{
// Example, try to cast correct boxed
GdkEvent *e = va_arg(ap, GdkEvent *);
break;
}
}
}
va_end(ap);
}
Needs to correct return and boxed cast, but with this I can work fine
You should not use the same function for different types of callbacks. Some callbacks take different parameters, others have different return values — for instance, in your example, clicked does not return anything, whereas button-press-event returns a boolean value.
If you have common code that needs to be executed in different signal handlers, write a function and then call it from the various handlers.

Elegantly attempt to execute various functions a specific way

I'm attempting to execute various functions sequentially n number of times, only moving forward if previous function did not return false (error) otherwise I reset and start all over again.
An example of a sequence would be :
Turn module ON : module.power(true), 3 attempts
Wait for a signal : module.signal(), 10 attempts
Send a message : module.sendSMS('test'), 3 attempts
Turn module OFF : module.power(false), 1 attempt
Each of those actions are done the same way, only changing the DEBUG text and the function to launch :
DEBUG_PRINT("Powering ON"); // This line changes
uint8_t attempts = 0;
uint8_t max_attempts = 3; // max_attempts changes
while(!module.power(true) && attempts < max_attempts){ // This line changes
attempts++;
DEBUG_PRINT(".");
if(attempts == max_attempts) {
DEBUG_PRINTLN(" - Failed.");
soft_reset(); // Start all over again
}
delay(100);
}
DEBUG_PRINTLN(" - Success");
wdt_reset(); // Reset watchdog timer, ready for next action
Is there an elegant way I can put this process in a function I could call to execute the required functions this particular way, for example something like :
void try_this_action(description, function, n_attempts)
Which would make actions 1-4 above like :
try_this_action("Powering ON", module.power(true), 3);
try_this_action("Waiting for signal", module.signal(), 10);
try_this_action("Sending SMS", module.sendSMS('test'), 3);
try_this_action("Powering OFF", module.power(false), 1);
A difficulty I have is that the functions called have different syntax (some take parameters, some other don't...). Is there a more elegant modulable way of doing this besides copy/paste the chunck of code everywhere I need it ?
A difficulty I have is that the functions called have different syntax
(some take parameters, some other don't...).
That is indeed an issue. Along with it you have the possibility of variation in actual function arguments for the same function.
Is there a more elegant
modulable way of doing this besides copy/paste the chunck of code
everywhere I need it ?
I think you could make a variadic function that uses specific knowledge of the functions to dispatch in order to deal with the differing function signatures and actual arguments. I'm doubtful that I would consider the result more elegant, though.
I would be inclined to approach this job via a macro, instead:
// desc: a descriptive string, evaluated once
// action: an expression to (re)try until it evaluates to true in boolean context
// attempts: the maximum number of times the action will be evaluated, itself evaluated once
#define try_this_action(desc, action, attempts) do { \
int _attempts = (attempts); \
DEBUG_PRINT(desc); \
while(_attempts && !(action)) { \
_attempts -= 1; \
DEBUG_PRINT("."); \
delay(100); \
} \
if (_attempts) { \
DEBUG_PRINTLN(" - Success"); \
} else { \
DEBUG_PRINTLN(" - Failed."); \
soft_reset(); \
} \
wdt_reset(); \
} while (0)
Usage would be just as you described:
try_this_action("Powering ON", module.power(true), 3);
etc.. Although the effect is as if you did insert the code for each action in each spot, using a macro such as this would yield code that is much easier to read, and that is not lexically repetitive. Thus, for example, if you ever need to change the the steps for trying actions, you can do it once for all by modifying the macro.
You need to make the function pointers all have the same signature. I would use something like this;
typedef int(*try_func)(void *arg);
And have a try_this_action(...) signature similar to the following;
void try_this_action(char * msg, int max_trys, try_func func, void *arg)
You would then implement your actions similar to this;
int power(void *pv)
{
int *p = pv;
int on_off = *p;
static int try = 0;
if (on_off && try++)
return 1;
return 0;
}
int signal(void *pv)
{
static int try = 0;
if (try++ > 6)
return 1;
return 0;
}
And call them like this;
int main(int c, char *v[])
{
int on_off = 1;
try_this_action("Powering ON", 3, power, &on_off);
try_this_action("Signaling", 10, signal, 0);
}
Functions of different arity may be abstracted with a generic signature (think about main). Instead of each giving each their own unique arguments, you simply supply them all with:
An argument count.
A vector of pointers to the arguments.
This is how your operating system treats all programs it runs anyways. I've given a very basic example below which you can inspect.
#include <stdio.h>
#include <stdlib.h>
/* Define total function count */
#define MAX_FUNC 2
/* Generic function signature */
typedef void (*func)(int, void **, const char *);
/* Function pointer array (NULL - initialized) */
func functions[MAX_FUNC];
/* Example function #1 */
void printName (int argc, void **argv, const char *desc) {
fprintf(stdout, "Running: %s\n", desc);
if (argc != 1 || argv == NULL) {
fprintf(stderr, "Err in %s!\n", desc);
return;
}
const char *name = (const char *)(argv[0]);
fprintf(stdout, "Name: %s\n", name);
}
/* Example function #2 */
void printMax (int argc, void **argv, const char *desc) {
fprintf(stdout, "Running: %s\n", desc);
if (argc != 2 || argv == NULL) {
fprintf(stderr, "Err in %s!\n", desc);
return;
}
int *a = (int *)(argv[0]), *b = (int *)(argv[1]);
fprintf(stdout, "Max: %d\n", (*a > *b) ? *a : *b);
}
int main (void) {
functions[0] = printName; // Set function #0
functions[1] = printMax; // Set function #1
int f_arg_count[2] = {1, 2}; // Function 0 takes 1 argument, function 1 takes 2.
const char *descs[2] = {"printName", "printMax"};
const char *name = "Natasi"; // Args of function 0
int a = 2, b = 3; // Args of function 1
int *args[2] = {&a, &b}; // Args of function 1 in an array.
void **f_args[2] = {(void **)(&name),
(void **)(&args)}; // All function args.
// Invoke all functions.
for (int i = 0; i < MAX_FUNC; i++) {
func f = functions[i];
const char *desc = descs[i];
int n = f_arg_count[i];
void **args = f_args[i];
f(n, args, desc);
}
return EXIT_SUCCESS;
}
You can use a variadic function, declaring in the parameter list first those parameters that are always present, then the variable part.
In following code we define a type for action functions, void returning having as parameter an argument list:
typedef void (*action)(va_list);
Then define the generic action routine that prepare for the action execution:
void try_this_action(char *szActionName, int trials, action fn_action, ...)
{
va_list args;
va_start(args, fn_action); //Init the argument list
DEBUG_PRINT(szActionName); // This line changes
uint8_t attempts = 0;
uint8_t max_attempts = trials; // max_attempts changes
//Here we call our function through the pointer passed as argument
while (!fn_action(args) && attempts < max_attempts)
{ // This line changes
attempts++;
DEBUG_PRINT(".");
if (attempts == max_attempts)
{
DEBUG_PRINTLN(" - Failed.");
soft_reset(); // Start all over again
}
delay(100);
}
DEBUG_PRINTLN(" - Success");
wdt_reset(); // Reset watchdog timer, ready for next action
va_end(args);
}
Each function must be coded to use an argument list:
int power(va_list args)
{
//First recover all our arguments using the va_arg macro
bool cond = va_arg(args, bool);
if (cond == true)
{
... //do something
return true;
}
return false;
}
The usage will be:
try_this_action("Powering ON", 3, module.power, true);
try_this_action("Waiting for signal", 10, module.signal);
try_this_action("Sending SMS", 3, module.sendSMS, "test");
try_this_action("Powering OFF", 1, module.power, false);
If you need more info on variadic functions and usage of stdarg.h macros google the net. Start from here https://en.cppreference.com/w/c/variadic.
It could be coded also as a macro implementation, as the excellent proposal in the John Bollinger answer, but in that case you must consider that each macro usage will instantiate the whole code, that could be eventually even better for speed (avoiding a function call), but could be not suitable on systems with limited memory (embedded), or where you need reference to the function try_this_action (inexistent).

libclang get primitive value

How can I get the value of a primitive literal using libclang?
For example, if I have a CXCursor of cursor kind CXCursor_IntegerLiteral, how can I extract the literal value.
UPDATE:
I've run into so many problems using libclang. I highly recommend avoiding it entirely and instead use the C++ interface clang provides. The C++ interface is highly useable and very well documented: http://clang.llvm.org/doxygen/annotated.html
The only purpose I see of libclang now is to generate the ASTUnit object for you as with the following code (it's not exactly easy otherwise):
ASTUnit * astUnit;
{
index = clang_createIndex(0, 0);
tu = clang_parseTranslationUnit(
index, 0,
clangArgs, nClangArgs,
0, 0, CXTranslationUnit_None
);
astUnit = static_cast<ASTUnit *>(tu->TUData);
}
Now you might say that libclang is stable and the C++ interface isn't. That hardly matters, as the time you spend figuring out the AST with libclang and creating kludges with it wastes so much of your time anyway. I'd just as soon spend a few hours fixing up code that does not compile after a version upgrade (if even needed).
Instead of reparsing the original, you already have all the information you need inside the translation unit :
if (kind == CXCursor_IntegerLiteral)
{
CXSourceRange range = clang_getCursorExtent(cursor);
CXToken *tokens = 0;
unsigned int nTokens = 0;
clang_tokenize(tu, range, &tokens, &nTokens);
for (unsigned int i = 0; i < nTokens; i++)
{
CXString spelling = clang_getTokenSpelling(tu, tokens[i]);
printf("token = %s\n", clang_getCString(spelling));
clang_disposeString(spelling);
}
clang_disposeTokens(tu, tokens, nTokens);
}
You will see that the first token is the integer itself, the next one is not relevant (eg. it's ; for int i = 42;.
If you have access to a CXCursor, you can make use of the clang_Cursor_Evaluate function, for example:
CXChildVisitResult var_decl_visitor(
CXCursor cursor, CXCursor parent, CXClientData data) {
auto kind = clang_getCursorKind(cursor);
switch (kind) {
case CXCursor_IntegerLiteral: {
auto res = clang_Cursor_Evaluate(cursor);
auto value = clang_EvalResult_getAsInt(res);
clang_EvalResult_dispose(res);
std::cout << "IntegerLiteral " << value << std::endl;
break;
}
default:
break;
}
return CXChildVisit_Recurse;
}
Outputs:
IntegerLiteral 42
I found a way to do this by referring to the original files:
std::string getCursorText (CXCursor cur) {
CXSourceRange range = clang_getCursorExtent(cur);
CXSourceLocation begin = clang_getRangeStart(range);
CXSourceLocation end = clang_getRangeEnd(range);
CXFile cxFile;
unsigned int beginOff;
unsigned int endOff;
clang_getExpansionLocation(begin, &cxFile, 0, 0, &beginOff);
clang_getExpansionLocation(end, 0, 0, 0, &endOff);
ClangString filename = clang_getFileName(cxFile);
unsigned int textSize = endOff - beginOff;
FILE * file = fopen(filename.c_str(), "r");
if (file == 0) {
exit(ExitCode::CANT_OPEN_FILE);
}
fseek(file, beginOff, SEEK_SET);
char buff[4096];
char * pBuff = buff;
if (textSize + 1 > sizeof(buff)) {
pBuff = new char[textSize + 1];
}
pBuff[textSize] = '\0';
fread(pBuff, 1, textSize, file);
std::string res(pBuff);
if (pBuff != buff) {
delete [] pBuff;
}
fclose(file);
return res;
}
You can actually use a combination of libclang and the C++ interface.
The libclang CXCursor type contains a data field which contains references to the underlying AST nodes.
I was able to successfully access the IntegerLiteral value by casting data[1] to the IntegerLiteral type.
I'm implementing this in Nim so I will provide Nim code, but you can likely do the same in C++.
let literal = cast[clang.IntegerLiteral](cursor.data[1])
echo literal.getValue().getLimitedValue()
The IntegerLiteral type is wrapped like so:
type
APIntObj* {.importcpp: "llvm::APInt", header: "llvm/ADT/APInt.h".} = object
# https://github.com/llvm-mirror/llvm/blob/master/include/llvm/ADT/APInt.h
APInt* = ptr APIntObj
IntegerLiteralObj* {.importcpp: "clang::IntegerLiteral", header: "clang/AST/Expr.h".} = object
IntegerLiteral* = ptr IntegerLiteralObj
proc getValue*(i: IntegerLiteral): APIntObj {.importcpp: "#.getValue()".}
# This is implemented by the superclass: https://clang.llvm.org/doxygen/classclang_1_1APIntStorage.html
proc getLimitedValue*(a: APInt | APIntObj): culonglong {.importcpp: "#.getLimitedValue()".}
Hope this helps someone :)

Function has corrupt return value

I have a situation in Visual C++ 2008 that I have not seen before. I have a class with 4 STL objects (list and vector to be precise) and integers.
It has a method:
inline int id() { return m_id; }
The return value from this method is corrupt, and I have no idea why.
debugger screenshot http://img687.imageshack.us/img687/6728/returnvalue.png
I'd like to believe its a stack smash, but as far as I know, I have no buffer over-runs or allocation issues.
Some more observations
Here's something that puts me off. The debugger prints right values in the place mentioned // wrong ID.
m_header = new DnsHeader();
assert(_CrtCheckMemory());
if (m_header->init(bytes, size))
{
eprintf("0The header ID is %d\n", m_header->id()); // wrong ID!!!
inside m_header->init()
m_qdcount = ntohs(h->qdcount);
m_ancount = ntohs(h->ancount);
m_nscount = ntohs(h->nscount);
m_arcount = ntohs(h->arcount);
eprintf("The details are %d,%d,%d,%d\n", m_qdcount, m_ancount, m_nscount, m_arcount);
// copy the flags
// this doesn't work with a bitfield struct :(
// memcpy(&m_flags, bytes + 2, sizeof(m_flags));
//unpack_flags(bytes + 2); //TODO
m_init = true;
}
eprintf("Assigning an id of %d\n", m_id); // Correct ID.
return
m_header->id() is an inline function in the header file
inline int id() { return m_id; }
I don't really know how best to post the code snippets I have , but here's my best shot at it. Please do let me know if they are insufficient:
Class DnsHeader has an object m_header inside DnsPacket.
Main body:
DnsPacket *p ;
p = new DnsPacket(r);
assert (_CrtCheckMemory());
p->add_bytes(buf, r); // add bytes to a vector m_bytes inside DnsPacket
if (p->parse())
{
read_packet(sin, *p);
}
p->parse:
size_t size = m_bytes.size(); // m_bytes is a vector
unsigned char *bytes = new u_char[m_bytes.size()];
copy(m_bytes.begin(), m_bytes.end(), bytes);
m_header = new DnsHeader();
eprintf("m_header allocated at %x\n", m_header);
assert(_CrtCheckMemory());
if (m_header->init(bytes, size)) // just set the ID and a bunch of other ints here.
{
size_t pos = DnsHeader::SIZE; // const int
if (pos != size)
; // XXX perhaps generate a warning about extraneous data?
if (ok)
m_parsed = true;
}
else
{
m_parsed = false;
}
if (!ok) {
m_parsed = false;
}
return m_parsed;
}
read_packet:
DnsHeader& h = p.header();
eprintf("The header ID is %d\n", h.id()); // ID is wrong here
...
DnsHeader constructor:
m_id = -1;
m_qdcount = m_ancount = m_nscount = m_arcount = 0;
memset(&m_flags, 0, sizeof(m_flags)); // m_flags is a struct
m_flags.rd = 1;
p.header():
return *m_header;
m_header->init: (u_char* bytes, int size)
header_fmt *h = (header_fmt *)bytes;
m_id = ntohs(h->id);
eprintf("Assigning an id of %d/%d\n", ntohs(h->id), m_id); // ID is correct here
m_qdcount = ntohs(h->qdcount);
m_ancount = ntohs(h->ancount);
m_nscount = ntohs(h->nscount);
m_arcount = ntohs(h->arcount);
You seem to be using a pointer to an invalid class somehow. The return value shown is the value that VS usually uses to initialize memory with:
2^32 - 842150451 = 0xCDCDCDCD
You probably have not initialized the class that this function is a member of.
Without seeing more of the code in context.. it might be that the m_id is out of the scope you expect it to be in.
Reinstalled VC++. That fixed everything.
Thank you for your time and support everybody! :) Appreciate it!