菜鸟教程小白 发表于 2022-12-13 01:35:47

ios - Xcode 8.3 中奇怪的 Clang 行为


                                            <p><p>最近我注意到 Xcode 中 Objective C 内存管理的奇怪行为。
代码如下:</p>

<pre><code>#import &lt;Foundation/Foundation.h&gt;

int main(int argc, const char * argv[]) {
    @autoreleasepool {
      NSString *firstString = [ initWithString: @&#34;Hello&#34;];
      NSString *secondString = firstString;
      ;
      NSLog(@&#34;%@&#34;, secondString);
    }
    return 0;
}
</code></pre>

<p>我认为,释放 <strong>firstString</strong> 后 <strong>secondString</strong> 指向 <strong>nil</strong> 并且 <strong>NSLog</strong> 应该会产生错误。
但是此代码不会产生任何错误并成功打印“Hello”字符串。
我用这样的命令手动编译和运行代码,也没有发现任何错误:</p>

<pre><code>% clang -framework Foundation -fno-objc-arc main.m &amp;&amp; ./a.out
</code></pre>

<p>我尝试使用在线 Objective-C 编译器 (GCC) (<a href="http://rextester.com/l/objectivec_online_compiler" rel="noreferrer noopener nofollow">http://rextester.com/l/objectivec_online_compiler</a>) 编译此代码,但出现错误。
我究竟做错了什么?
ARC 支持在 Xcode 中被关闭。
提前致谢。</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>如果您执行静态分析(Xcode 中的 <kbd>shift</kbd>+<kbd>command</kbd>+<kbd>B</kbd>,或 Xcode 的“产品”菜单中的“分析”) ,它会警告你在对象被释放后你正试图引用它:</p>

<p> <a href="/image/53WKx.png" rel="noreferrer noopener nofollow"><img src="/image/53WKx.png" alt="static analysis"/></a> </p>

<p>问题在于,在手动引用计数代码中,您对已释放对象的引用<em>不会</em>自动设置为 <code>nil</code>。因此,除非您手动 <code>nil</code> 这些指针,否则您最终可能会得到指向先前已释放的对象的悬空指针。 </p>

<p>静态分析器非常擅长识别这类问题等。我建议您在继续之前确保静态分析仪的健康状况良好。</p>

<p>在这种情况下的第二道防线是启用僵尸运行时调试选项。这将报告在对象被释放后与对象交互的任何尝试。当您编辑 Xcode 目标的方案时,可以在“诊断”部分启用僵尸。 </p>

<p>不幸的是,您使用的是 <code>NSString</code>,它不遵循典型的内存管理规则(它可以保留自己对字符串的引用,因此它们并不总是在您期望的时候被释放他们是)。</p>

<p>考虑一个类似于你的例子,除了自定义类:</p>

<pre><code>#import &lt;Foundation/Foundation.h&gt;

@interface MyObject: NSObject
@end
@implementation MyObject
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
      MyObject *firstObject = [ init];
      MyObject *secondObject = firstObject;
      ;
      NSLog(@&#34;%@&#34;, secondObject);
    }
    return 0;
}
</code></pre>

<p>如果您在启动僵尸的情况下运行此程序,您将收到一条相应的错误消息,表明您正在尝试与已释放的实例进行交互:</p>

<blockquote>
<p>2017-05-27 08:19:18.154033-0700 MyApp *** -: message sent to deallocated instance 0x100303620</p>
</blockquote>

<p>但您可能不会从 <code>NSString</code> 收到此警告。最重要的是,应该避免从 <code>NSString</code> 行为中得出任何更广泛的内存管理结论。相反,请依赖 Xcode 的静态分析器和僵尸程序。 (注意,当您完成应用程序的调试时,请记得关闭僵尸。)</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - Xcode 8.3 中奇怪的 Clang 行为,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/44216327/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/44216327/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - Xcode 8.3 中奇怪的 Clang 行为