【问题标题】:Resolving cast to pointer from integer of different size error in 64-bit conversion解决在 64 位转换中从不同大小的整数转换为指针的错误
【发布时间】:2009-07-27 06:45:33
【问题描述】:

我正在努力将 PTHotKeyLib 修改为 64 位友好,但我在代码中遇到了一个问题,我不确定如何解决。在 PTHotKeyCenter 中, registerHotKey 方法创建一个 EventHotKeyID 实例,然后将 PTHotKey 对象填充到 id 属性中。原代码用了很长。我根据 Apple 的 64 位编程指南将其转换为 NSInteger。

  - (BOOL)registerHotKey:(PTHotKey *)theHotKey {
  OSStatus error;
  EventHotKeyID hotKeyID;
  EventHotKeyRef carbonHotKey;
  NSValue *key = nil;

  if ([[self allHotKeys] containsObject:theHotKey])
    [self unregisterHotKey:theHotKey];

  if (![[theHotKey keyCombo] isValidHotKeyCombo])
    return YES;

  hotKeyID.signature = kHotKeySignature;
  hotKeyID.id = (NSInteger)theHotKey;
  ... //Rest is not relevant
  }

当用户触发热键时,它会调用 sendCarbonEvent: 方法,该方法将尝试将 PTHotKey 实例从 EventHotKeyID 中拉出。它在 32 位领域工作,但在针对 64 位进行编译时,它会给出“从不同大小的整数转换为指针”警告

- (OSStatus)sendCarbonEvent:(EventRef)event {
  OSStatus error;
  EventHotKeyID hotKeyID;
  SGHotKey *hotKey;

  NSAssert(GetEventClass(event) == kEventClassKeyboard, @"Unknown event class");

  error = GetEventParameter(event,
                            kEventParamDirectObject, 
                            typeEventHotKeyID,
                            nil,
                            sizeof(EventHotKeyID),
                            nil,
                            &hotKeyID);
  if (error)
    return error;

  NSAssert(hotKeyID.signature == kHotKeySignature, @"Invalid hot key id" );
  NSAssert(hotKeyID.id != 0, @"Invalid hot key id");

  hotKey = (SGHotKey *)hotKeyID.id; // warning: cast to pointer from integer of different size
// Omitting the rest of the code
} 

从 x86_64 切换回 i386 会删除警告,并且所有内容都已编译并正常运行。在 x86_64 下它会导致崩溃,我不确定如何解决这个问题。关于如何解决它的任何建议?

【问题讨论】:

    标签: cocoa 64-bit macos-carbon


    【解决方案1】:

    不建议在指针和整数之间进行转换,因为这会导致代码不可移植。

    您所做的会导致 C99 定义为“未定义的行为”。这基本上意味着它可能会起作用,也可能不会。 C 语言以允许你做这样的事情而闻名,因为它隐含地假设你在输入它时知道你在做什么,并且你有神奇的 37337 mad Skillz 和多年的经验来知道什么时候做类似的事情是安全的这个和什么时候不是。

    可以肯定地说,这是安全的时代之一。

    从上下文来看,问题可能是由于将 64 位指针转换为 int 大小的变量。 Mac OS X 64 位 ABI 被称为 LP64,这意味着 longs 和 pointers 是 64 位宽,而 ints 是 32 位宽。所以,简而言之,在你的一次pointerint 和再次转换期间,你砍掉了前 32 位,而这恰好非常重要。

    查看文档,id 的类型是 UInt32。因此,简短的回答是您不能将 64 位指针放入 32 位大小的整数中。

    【讨论】:

      【解决方案2】:

      经典的答案是你做一个字典什么的,把字典的键放在id里,把指针放在值里,这样就避免了32位id里有实际的指针。

      但是你解决了吗?

      【讨论】:

      • 将指针放入一个太小而无法容纳指针的变量中是行不通的,无论指针指向什么。
      【解决方案3】:

      我刚刚在使用 PTHotKeysLib 时遇到了同样的问题。它只显示在 x86_64 架构中。

      为了解决这个问题,我查看了 SGHotKeysLib,它没有像上面那样尝试进行强制转换,而是在 64 位对象中存储了对 32 位指针的引用。然后当找到 32 位指针时,它会遍历所有 64 位对象(在本例中为 SGHotKey)以找到对 32 位指针的引用(在本例中为 EventHotKeyID。)

      进一步参考:https://github.com/secondgear/SGHotKeysLib/blob/master/SGHotKeysLib/SGHotKeyCenter.m

       for (SGHotKey *thisHotKey in [self allHotKeys]) {
          if ([thisHotKey matchesHotKeyID:hotKeyID]) {
            hotKey = thisHotKey;
            break;
          }
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-14
        • 1970-01-01
        • 2012-11-12
        相关资源
        最近更新 更多