相关疑难解决方法(0)

为什么structof sizeof不等于每个成员的sizeof总和?

为什么sizeof操作员返回的结构尺寸大于结构成员的总尺寸?

c c++ struct c++-faq sizeof

644
推荐指数
11
解决办法
18万
查看次数

C++标准是否允许未初始化的bool使程序崩溃?

我知道C++ 中的"未定义行为"几乎可以让编译器做任何想做的事情.但是,我遇到了让我感到惊讶的崩溃,因为我认为代码足够安全.

在这种情况下,真正的问题仅发生在使用特定编译器的特定平台上,并且仅在启用了优化时才发生.

我尝试了几件事来重现问题并将其简化到最大程度.这是一个名为的函数的摘录Serialize,它将获取bool参数,并将字符串true或复制false到现有的目标缓冲区.

如果bool参数是未初始化的值,那么这个函数是否会在代码审查中,没有办法告诉它实际上可能会崩溃?

// Zero-filled global buffer of 16 characters
char destBuffer[16];

void Serialize(bool boolValue) {
    // Determine which string to print based on boolValue
    const char* whichString = boolValue ? "true" : "false";

    // Compute the length of the string we selected
    const size_t len = strlen(whichString);

    // Copy string into destination buffer, which is zero-filled (thus already null-terminated)
    memcpy(destBuffer, whichString, len);
}
Run Code Online (Sandbox Code Playgroud)

如果使用clang 5.0.0 +优化执行此代码,它将/可能崩溃.

boolValue ? "true" …

c++ abi llvm undefined-behavior llvm-codegen

482
推荐指数
5
解决办法
3万
查看次数

为什么要快速运行glibc的问题太复杂了?

我在这里浏览strlen代码,想知道是否真的需要代码中使用的优化?例如,为什么下面这样的东西不能同样好或更好?

unsigned long strlen(char s[]) {
    unsigned long i;
    for (i = 0; s[i] != '\0'; i++)
        continue;
    return i;
}
Run Code Online (Sandbox Code Playgroud)

较简单的代码对编译器进行优化是否更好或更容易?

strlen链接后面页面上的代码如下所示:

/* Copyright (C) 1991, 1993, 1997, 2000, 2003 Free Software Foundation, Inc.
   This file is part of the GNU C Library.
   Written by Torbjorn Granlund (tege@sics.se),
   with help from Dan Sahlin (dan@sics.se);
   commentary by Jim Blandy (jimb@ai.mit.edu).

   The GNU C Library is free software; you can redistribute it and/or
   modify it under …
Run Code Online (Sandbox Code Playgroud)

c optimization portability glibc strlen

283
推荐指数
7
解决办法
5万
查看次数

为什么分段错误不可恢复?

我之前的问题之后,大多数评论都说“不要这样做,你处于一种不确定的状态,你必须杀死一切并重新开始”。还有一个“安全”的解决方法

我不明白的是为什么分段错误本质上是不可恢复的。

写入受保护内存的时刻被捕获 - 否则,将SIGSEGV不会被发送。

如果可以捕获写入受保护内存的时刻,我不明白为什么 - 理论上 - 它不能在某个低级别上恢复,并且不能将 SIGSEGV 转换为标准软件异常。

请解释为什么在分段错误之后程序处于不确定状态,因为很明显,在内存实际更改之前抛出了错误(我可能是错的,不明白为什么)。如果它被抛出,人们可以创建一个程序来更改受保护的内存,一次一个字节,出现分段错误,并最终重新编程内核 - 这种安全风险并不存在,因为我们可以看到世界仍然存在。

  1. 分段错误究竟何时发生(=何时发送SIGSEGV)?
  2. 为什么该进程在该点之后处于未定义的行为状态?
  3. 为什么无法恢复?
  4. 为什么这个解决方案可以避免这种不可恢复的状态?甚至吗?

c c++ exception segmentation-fault

112
推荐指数
11
解决办法
1万
查看次数

为什么memcmp(a,b,4)有时只针对uint32比较进行优化?

鉴于此代码:

#include <string.h>

int equal4(const char* a, const char* b)
{
    return memcmp(a, b, 4) == 0;
}

int less4(const char* a, const char* b)
{
    return memcmp(a, b, 4) < 0;
}
Run Code Online (Sandbox Code Playgroud)

x86_64上的GCC 7引入了第一种情况的优化(Clang已经做了很长时间):

    mov     eax, DWORD PTR [rsi]
    cmp     DWORD PTR [rdi], eax
    sete    al
    movzx   eax, al
Run Code Online (Sandbox Code Playgroud)

但第二种情况仍然是memcmp():

    sub     rsp, 8
    mov     edx, 4
    call    memcmp
    add     rsp, 8
    shr     eax, 31
Run Code Online (Sandbox Code Playgroud)

是否可以对第二种情况应用类似的优化?什么是最好的装配,有没有明确的理由为什么它没有完成(由GCC或Clang)?

在Godbolt的Compiler Explorer上看到它:https://godbolt.org/g/jv8fcf

c gcc x86-64 clang compiler-optimization

68
推荐指数
3
解决办法
3930
查看次数

我需要在 C 预处理器 #if 中测试一个值是否会创建一个 0 大小的数组

我有一个结构必须填充到 64K 才能完美地适合嵌入式项目,以便它填充闪存块。所以有一个#define将结构中的元素加起来使用sizeof()并确定pad[]最后需要多大才能使总大小为64K。

例如 :

#define SIZE_OF_MY_PAD (0x10000 - (sizeof(uint16_t) + sizeof(uint8_t)*32 + ... ))

typedef struct {
  uint16_t firstElement;
  uint8_t  secondElementArray[32];
  ...
  uint8_t pad[SIZE_OF_MY_PAD];
};
Run Code Online (Sandbox Code Playgroud)

这在很长一段时间内一直有效,直到突然我们在某些构建配置中根本不需要垫,因为它已经正好是 64k。这会导致代码失败,因为我们的编译器(不是 GCC)不允许pad[0].

我曾尝试过各种方法来创建一个预处理价值,我可以在使用#if声明中当检测到,但它总是失败,因为虽然sizeof()是合法的#define,它不是法律#if

c preprocessor

63
推荐指数
1
解决办法
4490
查看次数

确定C中动态分配的内存的大小

有没有办法在C中找出动态分配内存的大小?

例如,之后

char* p = malloc (100);
Run Code Online (Sandbox Code Playgroud)

有没有办法找出与之相关的内存大小p

c memory size allocation dynamic

56
推荐指数
6
解决办法
7万
查看次数

gcc,严格别名和恐怖故事

gcc-strict-aliasing-and-casting-through-a-union中,我问是否有人遇到过通过指针进行联合惩罚的问题.到目前为止,答案似乎是否定的.

这个问题是广泛的:你有任何关于gcc和严格走样恐怖故事?

背景:引用AndreyT在c99-strict-aliasing-rules-in-c-gcc中的答案:

"严格的别名规则植根于自[标准化]时代开始以来C和C++中存在的标准部分.禁止通过另一种类型的左值访问一种类型的对象的条款存在于C89/90中(6.3 )以及C++ 98(3.10/15)......并非所有编译器都希望(或敢于)强制执行或依赖它.

好吧,gcc现在敢于用它的-fstrict-aliasing开关来做到这一点.这引起了一些问题.例如,请参阅有关Mysql错误的优秀文章 http://davmac.wordpress.com/2009/10/,以及http://cellperformance.beyond3d.com/articles/2006/06/understanding中同样出色的讨论.-strict-aliasing.html.

其他一些不太相关的链接:

重复一遍,你有自己的恐怖故事吗?当然,没有表示的问题-Wstrict-aliasing是优选的.其他C编译器也很受欢迎.

6月2日补充:迈克尔伯尔的答案中的第一个链接,确实有资格作为恐怖故事,可能有点过时(从2003年开始).我做了一个快速测试,但问题显然已经消失了.

资源:

#include <string.h>
struct iw_event {               /* dummy! */
    int len;
};
char *iwe_stream_add_event(
    char *stream,               /* Stream of events */
    char *ends,                 /* End of stream */
    struct iw_event *iwe,       /* Payload */
    int event_len)              /* Real size of payload …
Run Code Online (Sandbox Code Playgroud)

c gcc strict-aliasing

51
推荐指数
4
解决办法
3万
查看次数

无法写入C中的屏幕内存

我是C的新手,它是继Java之后的第二种高级编程语言.我已经掌握了大部分基础知识,但无论出于何种原因,我无法将单个字符写入屏幕内存.

该程序使用Turbo C for DOS编译,运行速度为120mhz的Am486-DX4-100.该显卡是使用Trio32芯片的非常标准的VLB Diamond Multimedia Stealth SE.

对于操作系统,我运行的PC-DOS 2000加载了ISO代码页.我正在使用标准的MDA/CGA/EGA/VGA 80列文本模式运行.

这是我编写的程序:

#include <stdio.h>

int main(void) {
    unsigned short int *Video = (unsigned short int *)0xB8000;
    *Video = 0x0402;
    getchar();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

正如我所说,我对C很新,所以如果我的错误显而易见,我道歉,我无法找到一个可以理解的如何做到这一点的可靠来源.

据我所知,在x86平台上的实模式下,文本模式的屏幕内存从0xB8000开始.每个字符存储在两个字节中,一个用于字符,一个用于背景/前景.我的想法是将值0x0402(应该是一个红色的笑脸)写入0xB8000.这应该放在屏幕的左上角.

我已经考虑了屏幕可能滚动的可能性,因此在执行时会立即以两种方式删除我的角色.要解决此问题,我尝试过:

  • 使用循环重复写入此值
  • 再写下来吧.

我可以读取并打印我写入内存的值,所以它显然仍然在内存中,但无论出于何种原因,我都没有在屏幕上显示任何内容.我显然做错了,但我不知道会出现什么问题.如果需要任何其他细节,请询问.感谢您提供任何可能的帮助.

c x86 real-mode turbo-c x86-16

43
推荐指数
2
解决办法
3667
查看次数

对齐对C++ 11的性能是否真的重要?

对齐对C++ 11的性能是否真的重要?

在Stroustrup的书中有一条建议,要求从最大到最小的结构中对成员进行排序.但我想知道是否有人进行了测量,以确定是否会产生任何影响,并且在编写代码时是否值得考虑.

c++ memory-alignment c++11

38
推荐指数
2
解决办法
3756
查看次数