小编Dre*_*wen的帖子

功能回归

是否可以声明一些func_t返回该类型的函数类型,func_t

换句话说,函数是否可以返回自身?

// func_t is declared as some sort of function pointer
func_t foo(void *arg)
{
  return &foo;
}
Run Code Online (Sandbox Code Playgroud)

或者我必须使用void *和类型转换?

c function

29
推荐指数
2
解决办法
3540
查看次数

REPNZ SCAS汇编指令细节

我正在尝试对二进制文件进行逆向工程,以下指令让我感到困惑,有人可以澄清这究竟是什么吗?

=>0x804854e:    repnz scas al,BYTE PTR es:[edi]
  0x8048550:    not    ecx
Run Code Online (Sandbox Code Playgroud)

哪里:

EAX: 0x0
ECX: 0xffffffff
EDI: 0xbffff3dc ("aaaaaa\n")
ZF:  1
Run Code Online (Sandbox Code Playgroud)

我看到它在某种程度上以每次迭代递减1次ECX,并且EDI沿着字符串的长度递增.我知道它会计算字符串的长度,但至于它是如何发生的,以及为什么"al"涉及到我不太确定.

x86 assembly reverse-engineering

18
推荐指数
2
解决办法
1万
查看次数

"container_of"宏可以严格遵守吗?

linux内核(和其他地方)中常用的宏container_of是(基本上)定义如下:

#define container_of(ptr, type, member) (((type) *)((char *)(ptr) - offsetof((type), (member))))
Run Code Online (Sandbox Code Playgroud)

在给定指向其中一个成员的指针的情况下,它基本上允许恢复"父"结构:

struct foo {
    char ch;
    int bar;
};
...
struct foo f = ...
int *ptr = &f.bar; // 'ptr' points to the 'bar' member of 'struct foo' inside 'f'
struct foo *g = container_of(ptr, struct foo, bar);
// now, 'g' should point to 'f', i.e. 'g == &f'
Run Code Online (Sandbox Code Playgroud)

但是,并不完全清楚其中包含的减法是否container_of被视为未定义的行为.

一方面,因为barinside struct foo只是一个整数,所以只*ptr应该是有效的(以及ptr + 1).因此,container_of有效地产生一个表达式 …

c standards pointers

13
推荐指数
1
解决办法
691
查看次数

_Pragma和宏替换

在实现我自己的C11编译器时,我试图弄清楚如何处理_Pragma关键字/运算符.C11§6.10.9描述_Pragma为运算符,因此似乎可以用宏重新定义它,即#define _Pragma(x) SOME_OTHER_MACRO(x).此外,该声明#undef _Pragma应该没有影响(假设之前没有#define_Pragma).这类似于关键字#defined的方式,例如旧的VC++ hack #define for if (0) ; else for.但是,因为_Pragma在转换阶段3期间评估运算符,与执行预处理器指令的阶段相同,所以不清楚这是否是异常; 该标准未提及其未定义的行为是否_Pragma用作宏名称.

我使用以下代码对GCC进行了一些测试:

#define PRAGMA _Pragma
PRAGMA("message \"hi\"")

_Pragma ("message \"sup\"")

#undef PRAGMA

#undef _Pragma
//#define _Pragma(x)
_Pragma("message \"hello\"")
Run Code Online (Sandbox Code Playgroud)

使用gcc -std=c11 -pedantic -Wall -Wextra -c输出进行编译:

tmp.c:2:1: note: #pragma message: hi
 PRAGMA("message \"hi\"")
 ^
tmp.c:4:1: note: #pragma message: sup
 _Pragma ("message \"sup\"")
 ^
tmp.c:8:8: warning: undefining "_Pragma" [enabled by …
Run Code Online (Sandbox Code Playgroud)

c macros undefined-behavior

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

由C11 aligned_alloc分配的内存重新分配是否保持对齐?

考虑以下(C11)代码:

void *ptr = aligned_alloc(4096, 4096);
... // do something with 'ptr'
ptr = realloc(ptr, 6000);
Run Code Online (Sandbox Code Playgroud)

由于ptr指向的内存具有4096字节的对齐aligned_alloc,是否(读取:是否保证)在(成功)调用之后保持该对齐realloc?或者内存可以恢复为默认对齐?

c memory-management realloc c11

10
推荐指数
1
解决办法
1283
查看次数

wprintf:带有NULL指针的%p

在我编写单元测试时,我偶然发现了一些奇怪的行为glibc,关于"%p"NULL指针.

如果我有一条这样的线printf("NULL pointer is %p\n", NULL);,那么我看到NULL pointer is (nil)印在屏幕上,正如我所料.

如果我改为使用宽字符版本:wprintf(L"NULL pointer is %p\n", NULL);,则打印出来NULL pointer is (,并在左括号处停止.如果我打印非NULL指针,它会打印该指针,包括普通和宽字符版本.这是一个已知的错误glibc,或者我只是遗漏了什么?

注意:我意识到C标准说指针以%p实现定义的方式转换; 只是打印(一个NULL指针似乎不寻常.

c printf glibc widechar

7
推荐指数
1
解决办法
422
查看次数

将第一列数据文件读取为字符串

我有这样的dat文件

AAAA     1861    9   7   0.00    -1.50   -19.50      9999.00     9999.00     9999.00     9999.00     18.20   9999.00     6.70    135.00      8.00    9999.00     9999.00     9999.00     9999    0   193        250180280600000000 
BBBBBBBBB    1861    9   7   0.00    -7.50   36.50   9999.00     9999.00     21.40   1018.10     22.60   9999.00     1.00    68.00   2.00    9999.00     9999.00     9999.00     9999    0   193        451720280600000000 
VVVVVVVVV    1861    9   7   0.00    -58.50      10.50   9999.00     9999.00     27.50   9999.00     26.90   9999.00     15.40   45.00   6.00    9999.00     9999.00     9999.00     9999    0   193        357610280600000000 
SSSSSSSS     1861    9   7   0.00    117.50      13.50   9999.00     9999.00     28.00 …
Run Code Online (Sandbox Code Playgroud)

c++

7
推荐指数
2
解决办法
729
查看次数

避免显式构造函数调用虚拟基类

基本问题:是否可以避免必须显式调用每个虚拟基类的(非默认)构造函数?

背景:我正在开发围绕Windows COM对象的一些类型安全的C++包装器类.我目前的方法是有一个CBaseCOMWrapper类封装一个IUnknown对象进行引用计数.然后,我有一个CCOMWrapper模板类所继承CBaseCOMWrapper,它定义一个包装为特定COM类型(即IDXGIObject,ID3D11Device等).最后,单独的类从这些包装模板继承来提供实际的/额外的功能(即CDXGIObject,CD3D11Device).

例如,我有以下类(成员省略):

class CBaseCOMWrapper { };

template<typename T> // here, T should inherit from IUnknown
class CCOMWrapper : public virtual CBaseCOMWrapper { };

class CDXGIObject : public virtual CCOMWrapper<IDXGIObject> { };

template<>
class CCOMWrapper<IDXGIAdapter> : public virtual CCOMWrapper<IDXGIObject> { };

class CDXGIAdapter : public virtual CCOMWrapper<IDXGIAdapter> { };
Run Code Online (Sandbox Code Playgroud)

这是类型层次结构的对应图:

键入层次结构

左列是实际对象,中间列是瘦COM包装器,右列是实际COM对象.实线箭头表示继承,虚线箭头表示封装.

我使用模板特化CCOMWrapper来在中间提供父子关系.

问题:包装器类假定一个指向COM对象的非NULL(也就是有效)指针,所以我不能有一个默认的构造函数.因为层次结构充满了"钻石",所以大部分遗传都是虚拟的; 这意味着每个类的构造函数都必须调用构造函数.因此,在上面的例子中,构造函数CDXGIAdapter必须调用构造函数CCOMWrapper<IDXGIAdapter>, …

c++ com inheritance constructor virtual-inheritance

7
推荐指数
1
解决办法
266
查看次数

奇怪的gcc警告行为

我正在研究一个linux驱动程序,我收到了这条警告消息:

/home/andrewm/pivot3_scsif/pivot3_scsif.c:1090: warning: ignoring return value of ‘copy_from_user’, declared with attribute warn_unused_result
Run Code Online (Sandbox Code Playgroud)

违规行是:

  if (copy_from_user(tmp, buf, count) < 0)
Run Code Online (Sandbox Code Playgroud)

在检查声明之后copy_from_user,我发现它返回一个unsigned long,所以显然比较总是会失败,所以返回值不会影响比较.那部分是有道理的,但为什么gcc也没有警告它是签名/未签名的比较?这仅仅是编译器的特点吗?或者它是否避免同一表达式两次警告?

包含该行的函数是:

int proc_write(struct file *f, const char __user *buf, unsigned long count, void *data)
{
  char tmp[64];
  long value;
  struct proc_entry *entry;

  if (count >= 64)
    count = 64;
  if (copy_from_user(tmp, buf, count) < 0)
  {
    printk(KERN_WARNING "pivot3_scsif: failed to read from user buffer %p\n", buf);
    return (int)count;  
  }
  tmp[count - 1] = '\0';
  if …
Run Code Online (Sandbox Code Playgroud)

c linux gcc

5
推荐指数
1
解决办法
163
查看次数

为什么Solaris汇编程序生成的机器代码与GNU汇编程序不同?

我为amd64编写了这个小程序集文件.代码的作用对于这个问题并不重要.

        .globl fib

fib:    mov %edi,%ecx
        xor %eax,%eax
        jrcxz 1f
        lea 1(%rax),%ebx

0:      add %rbx,%rax
        xchg %rax,%rbx
        loop 0b

1:      ret
Run Code Online (Sandbox Code Playgroud)

然后我继续组装,然后在Solaris和Linux上反汇编.

的Solaris

$ as -o y.o -xarch=amd64 -V y.s                            
as: Sun Compiler Common 12.1 SunOS_i386 Patch 141858-04 2009/12/08
$ dis y.o                                                  
disassembly for y.o


section .text
    0x0:                    8b cf              movl   %edi,%ecx
    0x2:                    33 c0              xorl   %eax,%eax
    0x4:                    e3 0a              jcxz   +0xa      <0x10>
    0x6:                    8d 58 01           leal   0x1(%rax),%ebx
    0x9:                    48 03 c3           addq   %rbx,%rax
    0xc:                    48 93              xchgq  %rbx,%rax …
Run Code Online (Sandbox Code Playgroud)

linux assembly solaris x86-64

5
推荐指数
1
解决办法
339
查看次数