【问题标题】:collect2: error: ld returned 1 exit status (Pebble - C)collect2:错误:ld 返回 1 个退出状态(Pebble - C)
【发布时间】:2014-12-31 23:05:17
【问题描述】:

我是一名程序员,拥有强大的 Java for Android 背景。我对 C 语言非常陌生,我只是学习它来为 Pebble 编写配套应用程序。 编辑:我使用的是 cloudpebble,所以我无法控制库。

这是我认为问题所在的代码部分的摘要:

#include <pebble.h>

static int s_time_a_min;
static int s_time_a_h;
static int s_time_b_min = 0;
static int s_time_b_h = 0;
static int s_time_b_total;
char* c_time_string_min;
char* c_time_string_h;

int str_cut(char *str, int begin, int len){ //I got this method from the internet
    int l = strlen(str);

    if (len < 0) len = l - begin;
    if (begin + len > l) len = l - begin;
    memmove(str + begin, str + begin + len, l - len + 1);

    return len;
}

static void update_text(){
    time_t current_time;

    c_time_string_min = ctime(&current_time); //set these two strings the same: current time
    c_time_string_h = ctime(&current_time); //they are only strings so that they can be substringed

    c_time_string_min = str_cut(c_time_string_min, 14, 16); //substring so that the each string has either min or h
    c_time_string_h = str_cut(c_time_string_h, 11, 13); 

    s_si_h = atoi(c_time_string_h); //make the strings integers so that I can do math with them
    s_si_min = atoi(c_time_string_min);

    s_time_b_total = (((s_si_h) * 3600) + ((s_si_min) * 60)) * (123/99); //do some math. Don't ask what it's for.

    do{
        s_time_b_total = s_time_b_total - 10000; //do some more math. Also don't ask what it's for.
        s_time_b_h = s_time_b_h + 1;
    }while(s_ra_all > 10000);

    do{
        s_time_b_total = s_time_b_total - 100;
        s_time_b_min = s_time_b_min + 1;
    }while(s_ra_all > 100);

    //Here is where I think the problem lies.
    const char* buf = (char)(((int)0)+s_time_b_h) + ":" + (char)(((int)0)+s_time_b_min); //create a string that merges the two integers together and puts a colon in the middle                        

    text_layer_set_text(s_time_layer, buf); //Set text
}

然后是通常的 Window_load、main、init 等。

请告诉我我做错了什么。谢谢。

【问题讨论】:

  • 您的问题不在于代码,而是在链接时您未能包含某些库?
  • 这是一个链接器错误,而不是编译器错误。向我们展示您的代码将无济于事。你是如何尝试链接的?完整的错误是什么?
  • 注意:不要认为对c_time_string_min = ctime(&amp;current_time); c_time_string_h = ctime(&amp;current_time); 的两次调用总是会同时返回。
  • 注意:在 C 中,* (123/99)* (1) 相同。

标签: c pebble-watch cloudpebble


【解决方案1】:

在 C 中,简单的数字相加不会形成字符串。

相反,创建一个缓冲区并打印到它。

// const char* buf = (char)(((int)0)+s_time_b_h) + ":" + 
//    (char)(((int)0)+s_time_b_min);

//create a string that merges 2 integers together and puts a colon in the middle
char   buf[100];
sprintf(buf, "%d:%d", s_time_b_h, s_time_b_min);

【讨论】:

    【解决方案2】:

    没有看到链接器错误,就不可能知道问题所在。发生链接器错误的一个常见原因是无法解析符号。当您有函数原型或变量声明但没有定义时,就会发生这种情况。考虑:

    #include <stdio.h>
    extern char *foo;
    int main(void) { printf("%s\n", foo); return 0; }
    

    编译时,你会看到这样的输出:

    [dho@zendev ~]$ cc test.c -o test
    /tmp/cc2ec2wu.o: In function `main':
    test.c:(.text+0x7): undefined reference to `foo'
    collect2: error: ld returned 1 exit status
    

    这个错误出现在链接阶段,因为编译器足够了解类型的大小来生成所有相关代码。链接最终二进制文件时,变量的存储位置是未知的。同样,考虑:

    #include <stdio.h>    
    int foo(void);
    int main(void) { foo(); return 0; }
    

    [dho@zendev ~]$ cc test.c -o test
    /tmp/cc8tgEsT.o: In function `main':
    test.c:(.text+0x5): undefined reference to `foo'
    collect2: error: ld returned 1 exit status
    

    再次,我们看到有足够的信息让编译器工作,但是在链接时,我们找不到 foo 符号的定义。

    在您的代码中,有两个符号既未声明也未定义:text_layer_set_texts_time_layerpebble.h 可能声明了这些符号,但您没有正确链接以解决它们。如果您做了类似的事情,我希望看到这一点

    cc test.c -o test
    

    代替

    cc test.c -o test -lpebble
    

    您突出显示的行不可能导致链接器错误,但它是有问题的。在 C 中,+ 运算符不连接字符串。因此,这条线并没有做你认为它正在做的事情:

    const char* buf = (char)(((int)0)+s_time_b_h) + ":" + (char)(((int)0)+s_time_b_min);
    

    此外,将整数转换为字符不会使该整数可以表示为具有相同逻辑值的字符串。 (即int i = 42; char c = (char)i; -> c'*',而不是 "42")。 s_time_b_hs_time_b_min 也不是整数,它们是指向字符的指针。 C 中的字符串是由NUL 字节终止的连续字符字节流(您会看到“NULL 字节”抛出,但这并不是非常正确)。从这行可以看出你对dynamic memory allocation or C strings 并不熟悉,它与Java 有很大的不同。

    您从ctime(3) 填充的字符串具有以下形式:

    "Wed Jun 30 21:49:08 1993\n"
    

    因此,它们包含换行符。即使您的代码按预期工作,buf 的输出也会如下所示:

    |Wed Jun 30 21:49:08 1993
    :Wed Jun 30 21:49:08 1993
    |
    

    在此示例中,我使用竖线字符来显示字符串的开始和结束位置。

    您对ctime(3) 的调用存在缺陷。您的值 current_time 未初始化,因此 ctime(3) 的输出未定义。此外,ctime(3) 不是可重入函数,因此您对它的两次调用会相互覆盖。因为ctime(3) 具有二级粒度,所以对于您的示例,这可能不是问题——两个调用将在同一秒内完成,并且它们都使用相同的输入种子(current_time)。要正确执行此操作,您需要(例如):

    time_t current_time;
    char *s_time_b_h;
    
    current_time = time(NULL);
    s_time_b_h = ctime(&current_time);
    

    因为ctime(3) 不是可重入的,并且您需要两个值,所以您需要在某处为它们分配内存。您可以简单地做到这一点,而不必担心动态内存分配:

    /* 
     * ctime(3) says "The reentrant version ctime_r() does the same, 
     * but stores the string in a user-supplied buffer which should have 
     * room for at least 26 bytes."
     *
     * 26 is length of string plus newline plus NUL byte.
     */
    #define CTIME_MAX_LEN 26
    char h_buf[CTIME_MAX_LEN], min_buf[CTIME_MAX_LEN];
    time_t current_time;
    char *s_time_b_h, *s_time_b_min;
    
    current_time = time(NULL);
    s_time_b_h = ctime_r(&current_time, h_buf);
    if (s_time_b_h == NULL) {
        return -1;
    }
    s_time_b_min = ctime_r(&current_time, h_buf);
    if (s_time_b_min == NULL) {
        return -1;
    }
    
    /* Get rid of newlines that you probably don't want */
    h_buf[CTIME_MAX_LEN - 2] = '\0';
    min_buf[CTIME_MAX_LEN - 2] = '\0';
    
    /* 
     * CTIME_MAX_LEN * 2 is enough space for both times, the
     * additional 2 bytes is enough for the colon and NUL-byte.
     */
    char o_buf[CTIME_MAX_LEN * 2 + 2];
    snprintf(o_buf, sizeof (o_buf), "%s:%s", h_buf, min_buf);
    text_layer_set_text(s_time_layer, o_buf);
    

    当然,除非您对ctime_r(3) 的调用使用不同的值,否则双方将是相同的。在您修复链接器错误之前,您仍然无法测试此代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-03
      • 1970-01-01
      • 1970-01-01
      • 2015-02-19
      • 2011-08-26
      • 2012-09-12
      • 1970-01-01
      相关资源
      最近更新 更多