關於 web service, unity, blogger 等軟體工程筆記

Global variables across share objects problem (Dynamic Linking Library in UNIX-like system)

Edit icon 沒有留言
Global variables across share objects problem

We had a program which link multiple share objects, and those objects exported same different same functions but same name global variables, then got a bug.

When met same name global variable values was different when linking two different library in Linux, just think weird and made some mechanisms to avoid, but... it became a horrible problem later and forced us to face this.

Sample Code

Here is two project sample code that cause bug when you try to link them in linux, you can get them on Github.

Share object A

// export.h
#ifndef AEXPORT_H
#define AEXPORT_H

extern "C" {
   extern int GetAValue();
}

#endif
// export.cpp
#include "export.h"
#include "value.h"

extern int GetAValue(){
   return g_value;
}
// value.h
#ifndef VALUE_H
#define VALUE_H

extern int g_value;

#endif
// value.cpp
#include "value.h"

int g_value = 1;

Share object B

// export.h
#ifndef BEXPORT_H
#define BEXPORT_H

extern "C" {
   extern int GetBValue();
}

#endif
// export.cpp
#include "export.h"
#include "value.h"

extern int GetBValue(){
   return g_value;
}
// value.h
#ifndef VALUE_H
#define VALUE_H

extern int g_value;

#endif
// value.cpp
#include "value.h"

int g_value = 2;

Execute

#include <iostream>
#include <dlfcn.h>
#include <stdlib.h>
#include "../a/export.h"
#include "../b/export.h"

using namespace std;

int main()
{
    int a = GetAValue();
    int b = GetBValue();

    cout << "A Value: " << a << ", B Value: " << b << endl;
    return 0;
}

Expect output, also same output on Windows

A Value: 1, B Value: 2

Output on Linux

A Value: 1, B Value: 1

What the hell! It was an reference error acts like this figure after printing memory address:

Global variables link error on Unix-like share objects

How to fix?

After searching answers in internet (see Reference), found out the global variables share was shared across the share objects in Unix-like systems, it is totally different from Windows systems. So, the sample code output was out of expect.

Using global variables, One Definition Rule should apply across multiple share objects. We don't, we need payoff now :(.

But it was a big work to rename them due to large project size. Also hard to remove all global variables by rewriting program. Fortunately, Those are C++ projects to export C-like functions, so easily solved this bug by adding namespace in the end. (another renaming...)

Conclusion

  • Should not use global variables in share objects
  • One definition rule should be take care when linked multi-share objects
  • Namespace is good way to identify functions & variables

Reference

沒有留言: