1

This seems like it should be simple but I wasn't able to find much related to it. I have structure which has different fields used to store data about the program operation. I want to log that data so that I can analyse it later. Attempting to continuously log data over the course of the programs operation eats up a lot of resources. Thus I would only like to call the logging function when the data has changed. I would love it if there was an efficient way to check whether the structure members have updated. Currently I am playing a shell game with 3 structures (old, current, and new) in order to detect when the data has changed. Thanks in advance.

Moeman69
  • 157
  • 1
  • 1
  • 6
  • 3
    You should think to develop an interface that gives set and get functions for struct members. If your code is doing modification on a global variable is gonna be hard to reach what you need. – LPs Mar 15 '16 at 16:40
  • with a good debugger, it should be possible to set a data watchpoint to your structure, it should also be possible to log the changed data into a file. – mfro Mar 15 '16 at 17:12

3 Answers3

0

You may track structures and its hashes in your log function.

Let you have a hash function:

int hash(void* ptr, size_t size);

Let you have a mapping from pointer to struct to struct's hash like:

/* Stores hash value for ptr*/
void ptr2hash_update_hash(void* ptr, int hash);
/* Remove ptr from mapping */
void ptr2hash_remove(void* ptr);
/* Returns 0 if ptr was not stored, or stored has otherwise*/
int ptr2hash_get_hash(void* ptr);

Then you may check if your object was changed between log calls like this:

int new_hash = hash(ptr, sizeof(TheStruct));
int old_hash = ptr2hash_get_hash(ptr);
if (old_hash == new_hash)
    return;

ptr2hash_update_hash(ptr, new_hash);
/* Then do the logging */

Don't forget to remove ptr from mapping when you do free(ptr) :)

Here is simple hash table implementation, you will need it to implement ptr2hash mapping. Simple hash functions are here.

Community
  • 1
  • 1
ivaigult
  • 6,198
  • 5
  • 38
  • 66
  • Hashing a struct value will only work if you can guarantee that any padding in the struct is filled with known byte values (usually zero-filled). – Ian Abbott Mar 15 '16 at 17:40
  • I don't believe that somebody could change padding value between logging calls – ivaigult Mar 15 '16 at 17:43
  • What if the struct contains a pointer to other data as a member, and the pointed data changes ? This method would somehow need to become recursive. – SirDarius Mar 15 '16 at 17:44
  • If I got it right, OP wants only to check if structure members were updated – ivaigult Mar 15 '16 at 17:48
  • @ivaigult: Yes, you're correct about the padding values in this case (unless they're doing something weird), although it is something to be aware of in the general case of hashing different struct objects of the same type. – Ian Abbott Mar 15 '16 at 17:59
0

If you're running on Linux (x86 or x86_64) then another possible approach is the following:

Install a segment descriptor for a non-writable segment in the local descriptor table using the modify_ldt system call. Place your data inside this segment (or install the segment such that your data structure is within it).

Upon write access, your process will receive a SIGSEGV (segmentation fault). Install a handler using sigaction to catch segmentation faults. Within that handler, first check that the fault occurred inside the previously set segment (si_addr member of the siginfo_t) and if so prepare to record a notification. Now, change the segment descriptor such that the segment becomes writable and return from the signal handler.

The write will now be performed, but you need a way to change the segment to be non-writable again and to actually check what was written and if your data actually changed.

A possible approach could be to send oneself (or a "delay" process and then back to the main process) another signal (SIGUSR1 for example), and doing the above in the handler for this signal.

  • Is this portable? No.
  • Is this relyable? No.
  • Is this easy to implement? No.

So if you can, and I really hope you do, use a interface like already suggested.

Daniel Jour
  • 15,896
  • 2
  • 36
  • 63
0

The easiest way what you can try is, You can just keep two structure pointers. Once you are receiving the new updated values that time you can just compare the new structure pointer with the old structure pointer, and if any difference is there you can detect it and then you can update to old structure pointer so that you can detect further changes in updated value in future.

typedef struct testStruct
{
    int x;
    float y;
}TESTSTRUCT;

TESTSTRUCT* getUpdatedValue()
{
    TESTSTRUCT *ptr;
    ptr->x = 5;
    ptr->y = 6;
    //You can put your code to update the value.
    return ptr;
}

void updateTheChange(TESTSTRUCT* oldObj,TESTSTRUCT* newObj)
{
    cout << "Change Detected\n";
    oldObj = newObj;
}

int main()
{
    TESTSTRUCT *oldObj = NULL;
    TESTSTRUCT *newObj = NULL;

    newObj = getUpdatedValue();

    //each time a value is updated compae with the old structure
    if(newObj == oldObj)
    {
        cout << "Same" << endl;
    }
    else
    {
        updateTheChange(oldObj,newObj);
    }

    return 0;
}

I am not sure, it gives you your exact answer or not.

Hope this Helps.

Sudipta Kumar Sahoo
  • 1,049
  • 8
  • 16