我在两台不同的计算机上使用以下功能。一台计算机正在运行Ubuntu,另一台计算机正在运行OSX。该功能在OS X上有效,但在Ubuntu上不起作用。

#include <stdio.h>

#define MAXBUF 256

char *safe_strncat(char *dest, const char *src, size_t n) {
    snprintf(dest, n, "%s%s", dest, src);
    return dest;
}

int main(int argc, const char * argv[]){
    char st1[MAXBUF+1] = "abc";
    char st2[MAXBUF+1] = "def";
    char* st3;
    printf("%s + %s = ",st1, st2);

    st3 = safe_strncat(st1, st2, MAXBUF);

    printf("%s\n",st3);
    printf("original string = %s\n",st1);
}
在Ubuntu上编译并运行

在OS X中的Xcode中编译并运行

  • 为什么在Mac而不是Ubuntu上可以使用?
  • 它可以在Ubuntu上运行吗?
  • 它是否可以在Mac上运行?
  • 我可以发誓它直到最近才可以在Ubuntu中使用,但是我不知道会发生什么变化才能使其停止工作?
  • 编译器设置是否与此工作有关?
  • 最佳答案

    您的代码调用了未定义的行为,因为您将目标缓冲区作为snprintf()格式的源字符串之一传递。不支持:



    (强调我的)。

    Ubuntu(glibc)和OS/X(Apple libc,基于BSD源)之间snprintf的实现有所不同。行为是不同的,不能被依赖,因为在所有情况下它都是不确定的。

    您可以通过以下方式实现safe_strcat():

    #include <string.h>
    
    char *safe_strcat(char *dest, size_t size, const char *src) {
        char *p = memchr(dest, '\0', size);
        if (p != NULL) {
            strncat(p, src, size - (p - dest) - 1);
        }
        return dest;
    }
    

    笔记:
  • 不要调用此函数safe_strncat(),它确实是strcat()的安全版本。
  • 在目标指针本身之后而不是在源指针之后传递目标数组的大小。
  • 返回目的地指针的
  • 不允许调用方检测到截断。如果目标数组足够大,则可以返回结果的长度,例如snprintf(),您仍然不会告诉调用方目标在调用之前是否不是以null终止的(对于safe_strcatsafe_strncat)。

  • 您可以对strcpystrncatstrncpy的安全版本使用相同的模型(但不能实现strncpy()的违反直觉的语义):
    char *safe_strcpy(char *dest, size_t size, const char *src) {
        if (size > 0) {
            *dest = '\0';
            strncat(dest, src, size - 1);
        }
        return dest;
    }
    
    char *safe_strncat(char *dest, size_t size, const char *src, size_t n) {
        char *p = memchr(dest, '\0', size);
        if (p != NULL) {
            if (n > size - (p - dest) - 1)
                n = size - (p - dest) - 1;
            strncat(p, src, n);
        }
        return dest;
    }
    
    char *safe_strncpy(char *dest, size_t size, const char *src, size_t n) {
        if (size > 0) {
            if (n > size - 1)
                n = size - 1;
            *dest = '\0';
            strncat(dest, src, n);
        }
        return dest;
    }
    

    关于c - c snprintf用于连接字符串,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40877721/

    10-11 22:05
    查看更多