TF_NewTensor 分段错误:可能的错误?

Posted

技术标签:

【中文标题】TF_NewTensor 分段错误:可能的错误?【英文标题】:TF_NewTensor Segmentation Fault: Possible Bug? 【发布时间】:2020-01-23 08:23:55 【问题描述】:

我正在使用 Tensorflow 2.1 git master 分支(提交 id:db8a74a737cc735bb2a4800731d21f2de6d04961)并在本地编译它。使用 C API 调用TF_LoadSessionFromSavedModel,但似乎出现分段错误。我已经设法深入了解下面示例代码中的错误。

TF_NewTensor 调用崩溃并导致分段错误。


int main()

    TF_Tensor** InputValues = (TF_Tensor**)malloc(sizeof(TF_Tensor*)*1);
    int ndims = 1;
    int64_t* dims = malloc(sizeof(int64_t));
    int ndata = sizeof(int32_t);
    int32_t* data = malloc(sizeof(int32_t));
    dims[0] = 1;
    data[0] = 10;

    // Crash on the next line
    TF_Tensor* int_tensor = TF_NewTensor(TF_INT32, dims, ndims, data, ndata, NULL, NULL);
    if(int_tensor == NULL)
    
        printf("ERROR");
    
    else
    
        printf("OK");
    
    return 0;

但是,当我在 TF_NewTensor 调用之后移动 TF_Tensor** InputValues = (TF_Tensor**)malloc(sizeof(TF_Tensor*)*1); 时,它不会崩溃。如下:


int main()


    int ndims = 1;
    int64_t* dims = malloc(sizeof(int64_t));
    int ndata = sizeof(int32_t);
    int32_t* data = malloc(sizeof(int32_t));
    dims[0] = 1;
    data[0] = 10;

    // NO more crash
    TF_Tensor* int_tensor = TF_NewTensor(TF_INT32, dims, ndims, data, ndata, NULL, NULL);
    if(int_tensor == NULL)
    
        printf("ERROR");
    
    else
    
        printf("OK");
    

    TF_Tensor** InputValues = (TF_Tensor**)malloc(sizeof(TF_Tensor*)*1);


    return 0;

这是一个可能的错误还是我用错了?我不明白mallocq 自变量如何导致分段错误。

任何人都可以复制吗?

我正在使用 gcc (Ubuntu 9.2.1-9ubuntu2) 9.2.1 20191008 进行编译。

更新:

可以进一步简化错误如下。这甚至没有分配InputValues


#include <stdlib.h>
#include <stdio.h>
#include "tensorflow/c/c_api.h"

int main()

    int ndims = 1;
    int ndata = 1;

    int64_t dims[] =  1 ;
    int32_t data[] =  10 ;

    TF_Tensor* int_tensor = TF_NewTensor(TF_INT32, dims, ndims, data, ndata, NULL, NULL);
    if(int_tensor == NULL)
    
        printf("ERROR Tensor");
    
    else
    
        printf("OK");
    

    return 0;

编译

gcc -I&lt;tensorflow_path&gt;/include/ -L&lt;tensorflow_path&gt;/lib test.c -ltensorflow -o test2.out

解决方案

正如 Raz 指出的那样,传递空的 deallocater 而不是 NULL,并且 ndata 应该是字节大小。

#include "tensorflow/c/c_api.h"
void NoOpDeallocator(void* data, size_t a, void* b) 

int main()
    int ndims = 2;
    int64_t dims[] = 1,1;
    int64_t data[] = 20;
    int ndata = sizeof(int64_t); // This is tricky, it number of bytes not number of element

    TF_Tensor* int_tensor = TF_NewTensor(TF_INT64, dims, ndims, data, ndata, &NoOpDeallocator, 0);
    if (int_tensor != NULL)\
        printf("TF_NewTensor is OK\n");
    else
        printf("ERROR: Failed TF_NewTensor\n");

在我的 Github 上查看运行/编译 TensorFlow 的 C API here的完整代码

【问题讨论】:

我没有看到 InputValues 在任何地方使用,那么这怎么可能是导致崩溃的原因? mallocInputValues 是否成功?我没有看到你检查。如果它失败了,那么在你的第一个代码中,其他 malloc 也可能失败。 ndata 是否表示data 的大小?因为你只分配了一个 int32 给它。 @PaulOgilvie 在这个例子中我没有使用InputValues,但在实际代码中,我使用它来调用SessionRun API。 malloc 确实返回非空值,我也尝试使用 ndata = 1,正如 Raz Haleva 所建议的那样。还是一样的分段错误 @PaulOgilvie 查看仍然产生分段错误的更新代码。 【参考方案1】:

您将ndata 设置为sizeof(int32_t),即4。 你的ndata 作为len 参数传递给TF_NewTensor(),它表示data 中的元素数量(可以在GitHub 中看到)。因此,在您的示例中应将其设置为 1,因为您只有一个元素。

顺便说一句,您可以避免在此处使用malloc()(因为您不检查返回值,这可能会出错并且通常不太优雅),而只需使用局部变量。

更新

此外,您将NULL 传递给deallocatordeallocator_arg。我很确定这是问题所在,因为评论指出 “客户端必须提供自定义解除分配器功能...”(可以看到 here)。 deallocatorTF_NewTensor() 调用(可见here),这可能是分段错误的原因。

所以,总结一下,试试下面的代码:

void my_deallocator(void * data, size_t len, void * arg)

    printf("Deallocator called with data %p\n", data);


void main()

    int64_t dims[] =  1 ;
    int32_t data[] =  10 ;

    ... = TF_NewTensor(TF_INT32, dims, /*num_dims=*/ 1, data, /*len=*/ 1, my_deallocator, NULL);

【讨论】:

我尝试将 ndata 设置为 1,但仍然出现相同的分段错误。另外,我更改了dimsdata,正如你提到的。我想知道其他人可以复制它还是只是在我的环境中。 有趣的是,如果我设置了我的 data,dimsndata,即使没有分配 InputValues,我也会遇到分段错误 请参考仍然崩溃的新代码更新。 @AmirulOm 请参阅更新部分,不要将NULL 传递给deallocatordeallocator_arg。如果有帮助,请告诉我! 谢谢,我通过 GDB 运行调试来计算它。有两个错误。 1) 将 NULL 传递给 deallocater,应该传递空 deallocater。 2)len实际上是字节大小,音符长度。

以上是关于TF_NewTensor 分段错误:可能的错误?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的字符串分配会导致分段错误?

分段错误,不确定来源

确定导致分段错误的代码行?

sort函数C ++分段错误

这段代码一次执行良好,另一次出现分段错误

为啥这段代码在 leetcode 运行良好,但在 geeksforgeeks 出现分段错误?