这是一个逻辑错误还是发生了什么?foreach的问题

这是一个逻辑错误还是发生了什么?foreach的问题,c,postgresql,C,Postgresql,我在c语言中有一个函数,它在Postgresql服务器上运行,名为get\u ndistint,它为Postgresql数据库中某些表的列返回get\u ndistint的统计值。 事实上,当foreach输入两次(第二次)时,在idxcd->varattnames[i]中加载的值在我看来是一个数字,而实际上我应该返回一个列名值。在我看来,出现的数字与在循环的前一步中为get\u ndistinct返回的值相匹配?我真的想了很多,我不明白为什么会这样。我不知道这是我的逻辑错误还是发生了什么。这很

我在c语言中有一个函数,它在Postgresql服务器上运行,名为get\u ndistint,它为Postgresql数据库中某些表的列返回get\u ndistint的统计值。 事实上,当foreach输入两次(第二次)时,在idxcd->varattnames[i]中加载的值在我看来是一个数字,而实际上我应该返回一个列名值。在我看来,出现的数字与在循环的前一步中为get\u ndistinct返回的值相匹配?我真的想了很多,我不明白为什么会这样。我不知道这是我的逻辑错误还是发生了什么。这很奇怪,尤其是因为数字与循环前一步返回的值一致。。。我不知道在idxcd->varattnombre[I]中它在哪里或如何加载? 要使用调试器,我不知道是否可以。。。因为我使用一个Makefile。我不知道我是否可以将调试器与Makefile一起使用,我是Linux新手。 请给我答复,我将不胜感激。 我的源代码如下:

/**
 * get_distinct
 *      for every candidate get an entry into IndexCandidate
 */
static List*
get_ndistinct( List* candidates )
{
    int proc;
    StringInfoData  query;  /* string for Query */
    StringInfoData  cols;   /* string for Columns */
    Oid             advise_oid;
    ListCell        *cell;
    IndexCandidate* idxcd;


    elog( DEBUG3, "IND ADV: get_distinct: ENTER" );



    initStringInfo( &query );
    initStringInfo( &cols );

    foreach( cell, candidates ) /* foreach cell in candidates */
    {
        idxcd = (IndexCandidate*)lfirst( cell );

        if (idxcd == NULL) {
            elog( INFO, "idxcd IS NULL" );
            continue; /* Or is that fatal enough to break instead? */
        }

        if (!idxcd->idxused)
            continue;

        int i;


        /* pfree() the memory allocated for the previous candidate. FIXME: Avoid
         * meddling with the internals of a StringInfo, and try to use an API.
         */
        if( cols.len > 0 )
        {
            initStringInfo(&cols);
        } /*IF col.len>0*/

        if( query.len > 0 )
        {
            initStringInfo(&query);
        } /*IF col.len>0*/


        appendStringInfo( &query, "select n_distinct from pg_stats where ");

        for (i = 0; i < idxcd->ncols; ++i)
        {


            appendStringInfo( &cols, "%s attname='%s'", (i>0?" OR":""), idxcd->varattnombres[i]);


        }/* foreach col in varattno*/


        /* FIXME: Mention the column names explicitly after the table name. */
        appendStringInfo( &query, "%s;", cols.data);



        if( query.len > 0 ) /* if we generated any SQL */
        {

            if( SPI_connect() == SPI_OK_CONNECT )
            {

                if( SPI_execute( query.data, true, 0 ) != SPI_OK_SELECT )
                        elog( WARNING, "IND ADV: SPI_execute failed while select." );

                else /* SPI_OK_SELECT*/
                {

                    proc=SPI_processed;
                    TupleDesc tupdesc=SPI_tuptable->tupdesc;
                    SPITupleTable *tuptable=SPI_tuptable;
                    char buf[8192];
                    int i,j;
                    for(j=0;j<proc;j++)
                    {
                        /*cada fila*/
                        HeapTuple tuple=tuptable->vals[j];
                        for (i=1,buf[0]=0;i<=tupdesc->natts;i++)
                        {
                            /* cada columna de cada fila*/
                            char *data;
                            data=SPI_getvalue(tuple,tupdesc,i);
                            idxcd->ndistinct[j]=data;

                            snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),"%s %s",data,(i==tupdesc->natts)?"": "|");
                        }

                        elog(INFO,"EXECQ:%s",buf);  


                    }

                }


                if( SPI_finish() != SPI_OK_FINISH )

                    elog( WARNING, "IND ADV: SPI_finish failed while select." );
            }
            else /* SPI_connect() != SPI_OK_CONNECT*/
                elog( WARNING, "IND ADV: SPI_connect failed while select." );
        } /*if( query.len > 0 ) if we generated any SQL */

    } /* foreach cell in candidates */          

        /* TODO: Propose to -hackers to introduce API to free a StringInfoData . */
        if ( query.len > 0 )
            pfree( query.data );

    elog( DEBUG3, "IND ADV: select: EXIT" );
    return candidates;
}

根据所提供的信息,不可能精确定位错误。由于foreach循环遍历传递给函数的列表,因此它取决于函数的调用方列表中的值。也许你应该开始看看那里

关于附加与生成文件无关的调试器:

确保使用-g选项编译。如果配置了PostgreSQL-enable调试,则会自动发生这种情况

在函数的开头放一个sleep10

启动PostgreSQL会话并使用SELECT pg_backend_pid;获取后端进程ID

调用函数并使用

gdb /path/to/postgres 12345
其中12345是后端进程ID


生成文件与调试器无关。生成文件控制可执行文件的生成方式。调试器在运行时逐步执行代码。一个与另一个无关。问题是我将idxcd->varattnombres[I]的值打印为整数值,使用%d,而实际上我必须将其打印为字符串值,使用%s,这就是我打印数值的原因。很高兴听到您在开发和调试PostgreSQL代码方面取得了进展。我从自己的经验中知道,令人尴尬的琐碎错误会让你困惑好几天。