Search code examples
c++luatorch

luaT_pushudata returns proper Tensor type and dimension, but garbage data


I have a short clip of C++ code that should theoretically work to create and return a torch.IntTensor object, but when I call it from Torch I get garbage data.

Here is my code (note this snippet leaves out the function registering, but suffice it to say that it registers fine--I can provide it if necessary):

static int ltest(lua_State* L)
{
    std::vector<int> matches;
    for (int i = 0; i < 10; i++)
    {
        matches.push_back(i);
    }

         performMatching(dist, matches, ratio_threshold);
         THIntStorage* storage = THIntStorage_newWithData(&matches[0], matches.size());
         THIntTensor* tensorMatches = THIntTensor_newWithStorage1d(storage, 0, matches.size(), 1);

    // Push result to Lua stack
    luaT_pushudata(L, (void*)tensorMatches, "torch.IntTensor");
    return 1;
}

When I call this from Lua, I should get a [torch.IntTensor of size 10] and I do. However, the data appears to be either memory addresses or junk:

 29677072
        0
 16712197
        3
        0
        0
 29677328
        0
  4387616
        0
[torch.IntTensor of size 10]

It should have been the numbers [0,9].

Where am I going wrong?


For the record, when I test it in C++

for (int i = 0; i < storage->size; i++)
    std::cout << *(storage->data+i) << std::endl;

prints the proper values.

As does

for (int i = 0; i < tensorMatches->storage->size; i++)
    std::cout << *(tensorMatches->storage->data+i) << std::endl;

so it seems clear to me that the problem lies in the exchange between C++ and Lua.


Solution

  • So I got an answer elsewhere--the Google group for Torch7--but I'll copy and paste it here for anyone who may need it.

    From user @alban desmaison:

    Your problem is actually memory management.

    When your C++ function return, you vector<int> is free, and so is its content. From that point onward, the tensor is pointing to free memory and when you access it, you access freed memory. You will have to either:

    • Allocate memory on the heap with malloc (as an array of ints) and use THIntStorage_newWithData as you currently do (the pointer that you give to newWithData will be freeed when it is not used anymore by Torch).
    • Use a vector<int> the way you currently do but create a new Tensor with a given size with THIntTensor_newWithSize1d(matches.size()) and then copy the content of the vector into the tensor.

    For the record, I couldn't get it to work with malloc but the copying memory approach worked just fine.