【问题标题】:Segmentation fault, can't find where I did wrong分段错误,找不到我做错的地方
【发布时间】:2015-05-07 07:31:23
【问题描述】:

我在我的树莓派的这个 C++ 代码中找不到我做错的地方,它给了我一个分段错误,但是在寻找 4 小时并在这里搜索之后,我没有发现任何错误

据我所知,当程序试图访问不属于他的内存时会发生分段错误,但我没有看到任何地方发生这种情况。

我基本上是在尝试使用树莓派模块找到某个颜色的对象

#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <unistd.h>
#include "RaspiCamCV.h"

using namespace cv;

int main(int argc, char *argv[ ]){

    RASPIVID_CONFIG * config = (RASPIVID_CONFIG*)malloc(sizeof(RASPIVID_CONFIG));

    config->width=320;
    config->height=240;
    config->bitrate=0;      // zero: leave as default
    config->framerate=0;
    config->monochrome=0;

    int opt;

    while ((opt = getopt(argc, argv, "lxm")) != -1)
    {
        switch (opt)
        {
            case 'l':                                       // large
                config->width = 640;
                config->height = 480;
                break;
            case 'x':                                       // extra large
                config->width = 960;
                config->height = 720;
                break;
            case 'm':                                       // monochrome
                config->monochrome = 1;
                break;
            default:
                fprintf(stderr, "Usage: %s [-x] [-l] [-m] \n", argv[0], opt);
                fprintf(stderr, "-l: Large mode\n");
                fprintf(stderr, "-x: Extra large mode\n");
                fprintf(stderr, "-l: Monochrome mode\n");
                exit(EXIT_FAILURE);
        }
    }

    /*
     Could also use hard coded defaults method: raspiCamCvCreateCameraCapture(0)
     */
    RaspiCamCvCapture * capture = (RaspiCamCvCapture *) raspiCamCvCreateCameraCapture2(0, config);
    free(config);

    CvFont font;
    double hScale=0.4;
    double vScale=0.4;
    int    lineWidth=1;

    cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC, hScale, vScale, 0, lineWidth, 8);

    cvNamedWindow("RaspiCamTest", 1);
    int exit = 0;
    IplImage* x;
    IplConvKernel* erodeElement;
    IplConvKernel* dilateElement;

    printf("start");


    do {
        IplImage* image = raspiCamCvQueryFrame(capture);
        cvCvtColor(image, x, COLOR_BGR2HSV);

        cvInRangeS(&x, cvScalar(0,137,171), cvScalar(48,256,248), x);

        char text[200];
        sprintf(text, "Press ESC to exit");
        cvPutText(x, text, cvPoint(05, 80), &font, cvScalar(255, 255, 0, 0));

        printf("hi");

        erodeElement = cvCreateStructuringElementEx(3,3,-1,-1,MORPH_RECT);
        dilateElement = cvCreateStructuringElementEx(6,6,-1,-1,MORPH_RECT);

        cvErode(x,x,erodeElement);
        cvErode(x,x,erodeElement);

        cvDilate(x,x,dilateElement);
        cvDilate(x,x,dilateElement);



        cvShowImage("RaspiCamTest2", static_cast<CvArr*>(&x));
        cvShowImage("RaspiCamTest", image);

        char key = cvWaitKey(10);

        switch(key)
        {
            case 27:                // Esc to exit
                exit = 1;
                break;
            case 60:                // < (less than)
                raspiCamCvSetCaptureProperty(capture, RPI_CAP_PROP_FPS, 25);    // Currently NOOP
                break;
            case 62:                // > (greater than)
                raspiCamCvSetCaptureProperty(capture, RPI_CAP_PROP_FPS, 30);    // Currently NOOP
                break;
        }

    } while (!exit);

    cvDestroyWindow("RaspiCamTest");
    raspiCamCvReleaseCapture(&capture);
    return 0;
}

【问题讨论】:

  • 使用 -g 标志编译并使用 gdb 检查发生段错误的位置
  • x在哪里初始化?
  • 就在“do {”行之前
  • "X 在 cvCvtColor(image,x,COLOR_BGR2HSV); 中初始化;" - 同样,不,它不是cvCvtColor 的第二个参数需要一个有效的内存地址。您正在向它发送一个不确定的地址。该参数应该是“与 src 大小和深度相同的输出图像”。你没有提供那个。
  • 由于 NULL 几乎不是“与 src 大小和深度相同的输出图像”,我将继续说 no。您需要完全按照描述创建图像目标;因此它具有与源图像相同的大小和深度。为什么不使用 OpenCV 的 C++ 绑定而不是 C 绑定,顺便说一句?或者问题是否被标记错误?

标签: c++ opencv segmentation-fault raspberry-pi


【解决方案1】:

这可能不是唯一的问题,但是当您将x 传递给cvCvtColor 时,它未初始化。您传递给 cvCvtColor 的dst 指针需要指向“与源图像具有相同数据类型的目标图像”。 (来自this page

这意味着cvCvtColor 调用将写入内存中的随机位置,可能立即或稍后导致崩溃。

【讨论】:

  • 哦,我以为 cvCvtColor 会初始化 x,我该如何以最快的方式初始化 x?
  • 我从来没有使用过 OpenCV,但是通过谷歌快速找到了这个页面:stackoverflow.com/questions/9211696/… 这表明你应该使用 x = cvCreateImage(cvGetSize(image), 8, 3); 虽然我不确定 83 应该是什么.
  • 很好,x 应该真正初始化。根据经验,始终将指针(至少使用NULLnullptr)和变量初始化为适当的值。 OpenCV 的 C-API 不会为您初始化变量(即使是输出参数)。
【解决方案2】:

除了以上几点:

为什么要在同一个函数调用中传递 'x' 和 'x' 本身的地址。

cvInRangeS(>>&x>x

其中一个似乎不正确。通过传入&x,是否打算分配空间并设置指针。如果是这样,为什么要单独传入'x'。

在 cvInRangeS() 的主体中,第二个 x 将指向未初始化的内存,即使您填写了与第一个参数对应的指针。

这是因为所有参数都被评估并传入,包括调用时存在的最后一个参数。第一个参数 '&x' 实现了更新调用者视图的副作用,但是,它在第​​二个参数的主体中不可用。

【讨论】:

    猜你喜欢
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-19
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    相关资源
    最近更新 更多