0
votes

I've cross-posted this on the Unity forums; apologies if this breaks conduct.

Hi folks

I've come across a crash that happens when I try to use an std::map in C++ from Unity through a plugin. I am not passing the contents of the map to Unity from the plugin; I am simply calling member functions such as the find() function (where my application crashes)

The code executes fine when I load my plugin into a C++ console application but it crashes in Unity. I suspect there is a marshalling/memory allocation issue where Unity is not allowing me to allocate memory of some sort

Attached is the Player.log output and the calling Unity script and the callee C++ code. Any help would be much appreciated.

Regards

Lancophone

Calling C# code:

public string filename; // The name of the audio file this behaviour corresponds to

[DllImport ("Unity-Audio-Plugin")]
private static extern void addSoundToRendererBank(string filename);

[DllImport ("Unity-Audio-Plugin")]
private static extern void addSoundToRendererBankAtPosition(string filename, float xPos, float zPos);

[DllImport ("Unity-Audio-Plugin")]
private static extern bool setSoundWithNameToPosition (string filename, float xPos, float zPos);

[DllImport ("Unity-Audio-Plugin")]
private static extern bool deactivateSoundInRendererBank (string filename);

// Use this for initialization
public int incr;
void Start () {
    incr = 1;
    addSoundToRendererBank (filename);
    InvokeRepeating ("moveMe", 0, 0.3F);
}
.....

Callee C++ code:

 void addSoundToRendererBank(char *filename)
 {
     printf("Calling the addSoundToRendererBank function with %s as a filename\n", filename);
     copyStringFromManagedCaller(filename);
     std::string fileNameStr(&buffer[0]);

     int soundLoc = soundBank->getIDForName(fileNameStr);
     if (soundLoc > 0) { // Sound is already in the bank
         // If its just been deactivated, reactivate it
         std::string key(&buffer[0]);
         soundBank->activateSoundSource(key);
     }
     ...
     ...
     int SoundBank::getIDForName(std::string &filePath)
     {
          // Filepath -> sourceIDMap -> source -> ID
          std::string key(filePath);
          int location;

          std::cerr << "About to enter the try-catch block in the SoundBank::getIDForName() function using " << key << std::endl;

          // Print the current elements inside the map
          std::cerr << "The contents of the sourceIDMap:" << std::endl;
          SoundSourceMapIterator map_it;
        //        for (map_it = sourceIDMap.begin(); map_it != sourceIDMap.end(); ++map_it) {
        //            std::cerr << "Key: " << map_it->first << "\tValue: " << map_it->second << std::endl;
        //        }
          std::cerr << "I'm about to die.... :-(" << std::endl;

          // Throws randomers; using find instead
          //        try
          //        {
          //            location = sourceIDMap.at(key);
          //        }
          //        catch (const std::out_of_range& oorEx)
          //        {
          //            location = -1;
          //        }

          SoundSourceMapIterator it = sourceIDMap.find(key);
          if (it == sourceIDMap.end())
              location = -1;
          else
              location = it->second;
          .......

Console output:

.....
The contents of the sourceIDMap:
I'm about to die.... :-(
Receiving unhandled NULL exception
Obtained 27 stack frames.
#0 0x00000111a00b91 in std::__1::__tree_iterator, std::__1::allocator >, int>, std::__1::__tree_node, std::__1::allocator >, int>, void*>*, long> std::__1::__tree, std::__1::allocator >, int>, std::__1::__map_value_compare, std::__1::allocator >, std::__1::__value_type, std::__1::allocator >, int>, std::__1::less, std::__1::allocator > >, true>, std::__1::allocator, std::__1::allocator >, int> > >::find, std::__1::allocator > >(std::__1::basic_string, std::__1::allocator > const&)
#1 0x000001119fdb21 in
uap::SoundBank::getIDForName(std::__1::basic_string, std::__1::allocator >&)
#2 0x00000111a06891 in addSoundToRendererBank
......

1
What do those functions do? copyStringFromManagedCaller(filename); std::string fileNameStr(&buffer[0]); And why are they connected through a buffer variable of unknown origin? I would expect it to have a return value.nvoigt
I added these as I thought the error was with marshalling strings. copyStringFromManagedCaller(filename) copies the filename variable to a static char[]. I then take the address of the buffer's first element in order to grab a char * to the buffer without const qualification. The code still crashes without this buffer (ie just passing the original filename char array through)Lancophone
@nvoigt Does that help?Lancophone
Sounds fishy, why don't you use a local buffer and return a string instead?nvoigt

1 Answers