Heap Corruption - C++ DLL call

Im gonna use a C++ plugin for my game. The pourpose of it is to keep track of highscore and player name of that highscore. The score itself works, but the player names have caused me a whole lot of trouble! The highscore is saved in one file, the player names are stored in another file, (.txt)Please help me understand what in the world is going wrong!

Code in C#

```csharp
*using UnityEngine;
using System.Runtime.InteropServices;
using System.Text;
using System;

public class highscoreManager : MonoBehaviour
{
//The imported function
[DllImport(“Assets/Plugins/highscorePlugin”)]
public static extern void saveHighscore(int score, int highscores);

[DllImport("Assets/Plugins/highscorePlugin")]
public static extern int loadHighscore(int[] highscores);

[DllImport("Assets/Plugins/highscorePlugin", CallingConvention = CallingConvention.Cdecl)]
public static extern void savePlayerNames(int score, int[] highscores, string playerName, string[] highscorePlayerNames);

[DllImport("Assets/Plugins/highscorePlugin", CallingConvention = CallingConvention.Cdecl)]
public static extern void loadPlayerNames(int[] highscores, StringBuilder[] highscorePlayerNamesDLLextract);

public int score;
public string playerName;
public int[] highscores;
public string[] highscorePlayerNames;
public StringBuilder[] highscorePlayerNamesDLLextract;

// Use this for initialization
void Update()
{
    if (Input.GetKeyDown(KeyCode.U))
    {
        save();
    }

    if (Input.GetKeyDown(KeyCode.I))
    {
        load();
    }
}

void save()
{
    saveHighscore(score, highscores);
    savePlayerNames(score, highscores, playerName, highscorePlayerNames);
    Debug.LogWarning("<color=purple>Highscore is being saved...</color>");
}

void load()
{
    loadHighscore(highscores);
    StringBuilder[] sb = new StringBuilder[(20)];
    loadPlayerNames(highscores, sb);
    convertSBtoString();
    Debug.LogWarning("<color=blue>Highscore data loaded!</color>");
}

void convertSBtoString()
{
    for (int i = 0; i <= 9; i++)
    {
        highscorePlayerNames[i] = highscorePlayerNamesDLLextract[i].ToString();
    }
}

}*
```

Code in C++ DLL

```csharp
*#include “highscore.h”
#include
#include
#include
#include

using namespace std;

extern “C”
{
HIGHSCORE_API void saveHighscore(int score, int highscores)
{
ofstream dataFile(fileNameOne);

    if (dataFile.is_open())
    {
        for (int i = 0; i <= 9; i++)
        {
            if (score > highscores[i])
            {
                for (int j = 9; j > i; j--)
                {
                    highscores[j] = highscores[j - 1];
                }

                highscores[i] = score;

                for (int k = 0; k <= 9; k++)
                {
                    dataFile << highscores[k] << "\n";
                }

                break;
            }

            if (score == 0)
            {
                for (int k = 0; k <= 9; k++)
                {
                    dataFile << highscores[k] << "\n";
                }

                break;
            }
        }
    }
}

HIGHSCORE_API void savePlayerNames(int score, int highscores[], char *playerName, const char *highscorePlayerNames[])
{
    ofstream dataFile(fileNameTwo);

    if (dataFile.is_open())
    {
        for (int i = 0; i <= 9; i++)
        {
            if (score > highscores[i])
            {
                for (int j = 9; j > i; j--)
                {
                    highscorePlayerNames[j] = highscorePlayerNames[j - 1];
                }

                highscorePlayerNames[i] = playerName;

                for (int k = 0; k <= 9; k++)
                {
                    dataFile << highscorePlayerNames[k] << "\n";
                }

                break;
            }

            if (playerName == "")
            {
                for (int k = 0; k <= 9; k++)
                {
                    dataFile << highscorePlayerNames[k] << "\n";
                }

                break;
            }
        }
    }
}

HIGHSCORE_API int loadHighscore(int highscores[])
{
    string data;
    int savedScore;

    ifstream dataFile(fileNameOne);

    if (dataFile.is_open())
    {
        int i = 0;

        for (int j = 0; j <= 9; j++)
        {
            highscores[j] = 0;
        }

        for (int i = 0; i <= 9; i++)
        {
            if (highscores[i] = 0)
            {
                break;
            }

            else
            {
                getline(dataFile, data);
                savedScore = stoi(data);
                highscores[i] = savedScore;
            }
        }

        return (highscores[i]);
    }
}

HIGHSCORE_API void loadPlayerNames(int highscores[], const char *highscorePlayerNames[])
{
    string data;

    ifstream dataFile(fileNameTwo, std::ios_base::app);

    if (dataFile.is_open())
    {
        int i = 0;

        for (int j = 0; j <= 9; j++)
        {
            highscorePlayerNames[j] = "";
        }

        for (int i = 0; i <= 9; i++)
        {
            if (highscores[i] = 0)
            {
                break;
            }

            else
            {
                getline(dataFile, data);

                const char* copyData = data.c_str();

                highscorePlayerNames[i] = copyData;
            }
        }
    }
}

}*
```

The problem is that when I press the assigned save / load button, Im supposed to take a string, apply it into a string array and write to file / read from file and apply in the array. What really happens is that Unity is freezing and crashes, when Im debugging in Visual Studios it says “A heap has been corrupted”. How could I fix this / rewrite the code so it works?

See this forum thread for ideas:

You need to pass the length of the array to the native plugin as it’s not possible to know how long it is otherwise.

This seems like… such overkill? Why do you need a plugin just to handle highscores? Is it meant to be just a learning thing, or is there a real reason you want to use a plugin for that?

1 Like

Seems a little overkill, unless you’re going for a whole framework that runs most of its time in C++ or you do some very heavy lifting on the C++ side, it’s not worth it.

Either way, you’re apparently trying to write to memory that you shouldn’t access.
While StringBuilders are one way to go, the C++ side still cannot just widly guess how much memory they’ve allocated for the internal character array and they cannot let it dynamically grow, so you need to initialize the StringBuilders with an appropriate initial capacity and should pass it along so that you can prevent the C++ side from overrunning your bounds.

That’s just one issue that appears to be happening here, but it’s surely not the only thing.

1 Like

Unless you’re just doing it as an exercise to learn native interop, as the posters above suggest, take five minutes and rewrite your C++ code in C# and you’re done. Instant cross-platform everywhere.