<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>cnicholson.net &#187; c++</title>
	<atom:link href="http://cnicholson.net/tag/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://cnicholson.net</link>
	<description>programming is hard.</description>
	<lastBuildDate>Mon, 24 Jan 2011 02:07:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Stupid C++ Tricks: do/while(0) and C4127</title>
		<link>http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/</link>
		<comments>http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/#comments</comments>
		<pubDate>Sun, 01 Mar 2009 17:33:41 +0000</pubDate>
		<dc:creator>charles</dc:creator>
				<category><![CDATA[Stupid C++ Tricks]]></category>
		<category><![CDATA[4127]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[C4127]]></category>
		<category><![CDATA[do]]></category>
		<category><![CDATA[while]]></category>

		<guid isPermaLink="false">http://cnicholson.net/?p=123</guid>
		<description><![CDATA[A nice little quickie:  I briefly discuss in my assert ramblings why it&#8217;s important to wrap all of your multi-line macros in do/while(0) blocks.  An unfortunate side-effect of this is that the construction // NOISY CODE #define MULTI_LINE_MACRO \ do { \ std::printf("Hello "); \ std::printf("world!\n"); \ } while (0) will trigger C4127: &#8220;Conditional expression [...]]]></description>
			<content:encoded><![CDATA[<p>A nice little quickie:  I briefly discuss in my <a href="http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/">assert ramblings</a> why it&#8217;s important to wrap all of your multi-line macros in <a href="http://kernelnewbies.org/FAQ/DoWhile0">do/while(0) blocks</a>.  An unfortunate side-effect of this is that the construction</p>
<pre name="code" class="c++:nocontrols">
// NOISY CODE
#define MULTI_LINE_MACRO \
	do { \
		std::printf("Hello "); \
		std::printf("world!\n"); \
	} while (0)
</pre>
<p>will trigger C4127: &#8220;Conditional expression is constant&#8221; in Visual Studio 2003/2005, and probably 2008 as well (but I haven&#8217;t tried it).  The culprit is the &#8220;while(0)&#8221; part, the compiler thinks we&#8217;re making a mistake when of course this is all very intentional.  Let&#8217;s see what we can do to fix it!<br />
<span id="more-123"></span></p>
<p>This is really unfortunate because these macros live in header files, and for the life of me I couldn&#8217;t figure out a way to shut up that warning!  The best way I&#8217;d found to deal with it was simply to issue a sledgehammer #pragma &#8220;shut the hell up&#8221; directive:</p>
<pre name="code" class="c++:nocontrols">
// QUIET BUT RUDE CODE
#pragma warning(disable:4127)
#define MULTI_LINE_MACRO \
	do { \
		std::printf("Hello "); \
		std::printf("world!\n"); \
	} while (0)
</pre>
<p>This is very bad.  I don&#8217;t want to globally silence 4127, just only for my multi-line macro stuff, but now every cpp file that #includes my header file has 4127 forever silenced!  This is inconvenient enough inside your own codebase, but it&#8217;s flat-out rude if you&#8217;re writing middleware!  I&#8217;ve used middleware that changes the warning levels on my cpp files, and it was an unpleasant surprise to find that the warnings I was expecting to receive were being muted before the compiler ever saw any of my code!</p>
<p>What we really want to do is something like this:</p>
<pre name="code" class="c++:nocontrols">
// BROKEN CODE
#define MULTI_LINE_MACRO \
	do { \
		std::printf("Hello "); \
		std::printf("world!\n"); \
#pragma warning(push)
#pragma warning(disable:4127)
	} while (0)
#pragma warning(pop)
</pre>
<p>This preserves the global warning state, but still disables 4127 for the duration of our intentional violation.  Unfortunately though, since the preprocessor isn&#8217;t recursive, that&#8217;s illegal.  We can&#8217;t put #pragma directives inside macro definitions!  We can also try doing something like this:</p>
<pre name="code" class="c++:nocontrols">
// STUPID CODE
#pragma warning(push)
#pragma warning(disable:4127)
#define MULTI_LINE_MACRO \
	do { \
		std::printf("Hello "); \
		std::printf("world!\n"); \
	} while (0)
#pragma warning(pop)
</pre>
<p>But that doesn&#8217;t do what we want at all, because of course the #pragmas don&#8217;t wrap the macro at its invocation site, and wrapping the definition doesn&#8217;t do anything!</p>
<p>Well, it turns out that Microsoft implemented the <a href="http://msdn.microsoft.com/en-us/library/d9x1s805.aspx">__pragma</a> directive for just this purpose.  Using __pragma instead of #pragma lets you embed pragma directives inside of macros!  This turns out to be just what the doctor ordered.  We can now throw together multi-line macro wrappers that emit no warnings on /W4 and don&#8217;t change the global warning state!</p>
<pre name="code" class="c++:nocontrols">
// WORKING CODE
#define MULTI_LINE_MACRO \
	do { \
		std::printf("Hello "); \
		std::printf("world!\n"); \
__pragma(warning(push)) \
__pragma(warning(disable:4127)) \
	} while (0) \
__pragma(warning(pop))
</pre>
<p>We can now generalize this approach to a set of helper macros that help you always correctly implement multi-line macros:</p>
<pre name="code" class="c++">
#define MULTI_LINE_MACRO_BEGIN do {
#define MULTI_LINE_MACRO_END \
	__pragma(warning(push)) \
	__pragma(warning(disable:4127)) \
	} while(0) \
	__pragma(warning(pop))
</pre>
<p>And here&#8217;s our original example reimplemented:</p>
<pre name="code" class="c++:nocontrols">
#define MULTI_LINE_MACRO \
	MULTI_LINE_MACRO_BEGIN \
		std::printf("Hello "); \
		std::printf("world!\n"); \
	MULTI_LINE_MACRO_END
</pre>
<p>Finally, I should point out that both a coworker of mine and <a href="http://lists.boost.org/Archives/boost/2004/09/72487.php">someone on the boost mailing list</a> have found another slightly bizarre workaround to this problem:  For some reason, the code</p>
<pre name="code" class="c++:nocontrols">
// WORKING CODE, BUT A LITTLE SCARY
#define MULTI_LINE_MACRO \
	do { \
		std::printf("Hello "); \
		std::printf("world!\n"); \
	} while (__LINE__ == -1)
</pre>
<p> <br />
doesn&#8217;t trigger C4127.  I can only conclude that it&#8217;s unintended compiler behavior, because replacing __LINE__ with a literal integer causes it to trigger, and I can&#8217;t imagine that MS intended that code to be the correct way to dodge 4127.  Use it at your own peril, and don&#8217;t be surprised if a new version of Visual Studio or some random service pack breaks it!</p>
]]></content:encoded>
			<wfw:commentRss>http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Stupid C++ Tricks: Adventures in Assert</title>
		<link>http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/</link>
		<comments>http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/#comments</comments>
		<pubDate>Wed, 11 Feb 2009 05:34:35 +0000</pubDate>
		<dc:creator>charles</dc:creator>
				<category><![CDATA[Stupid C++ Tricks]]></category>
		<category><![CDATA[assert]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://cnicholson.net/?p=3</guid>
		<description><![CDATA[This is a re-hosting of the original Assert article I wrote in April 2007,  during the epic rise and fall of Power of Two Games.  I&#8217;m reprinting it here on my personal site now that Pow2 is defunct and expired. Of the few reasons we failed, the lack of a good assert macro was not [...]]]></description>
			<content:encoded><![CDATA[<p>This is a re-hosting of the original Assert article I wrote in April 2007,  during the epic rise and fall of Power of Two Games.  I&#8217;m reprinting it here on my personal site now that Pow2 is defunct and expired.  Of the few reasons we failed, the lack of a good assert macro was not one of them!</p>
<p><span id="more-3"></span></p>
<p>Grab <a href="http://cnicholson.net/wp-content/uploads/2009/02/pow2assert.h">Pow2Assert.h</a> and <a href="http://cnicholson.net/wp-content/uploads/2009/02/pow2assert.cpp">Pow2Assert.cpp</a>, now under the MIT license!</p>
<p>The simple joys of hack-and-slash prototyping are over!  We&#8217;re convinced the gameplay is fun, so it&#8217;s time to buckle down and start coding &#8220;for real.&#8221;  We&#8217;re saying goodbye to the guilty pleasures of undisciplined C++ hacking and hello to solid, well-engineered code.  I recently had the pleasure of writing our assert macros and came across some surprisingly challenging problems.  This article is about how to make your assert macro as bulletproof as possible when you want it, and totally disappear into nothingness when you don&#8217;t.</p>
<p>We&#8217;re very aggressive about assert.  Noel even cared enough a couple years ago to <a href="http://www.lenholgate.com/archives/000527.html">stand up to the haters</a>!  We assert everything from pointer function parameters to Direct3D return codes.  We use it everywhere so it&#8217;s got to be absolutely rock solid.  &#8221;No problem,&#8221; you think, &#8220;assert is some beginner C++ stuff.  I&#8217;m a <a href="http://www.mcplusplus.com/">C++ animal</a>!  I can write assert macros in my sleep!&#8221;  Most assert code looks something like this (Assert::Fail is a function that does about what you&#8217;d expect, report the assert and terminate the program):</p>
<pre name="code" class="c++:nocontrols">
#define POW2_ASSERT(x) \
    if (!x) { pow2::Assert::Fail(#x, __FILE__, __LINE__); }
</pre>
<p>Take a minute right now and think of everything you&#8217;d fix about this assert macro.  If this code makes you run screaming for the hills (and scheduling a heart-to-heart with your lead programmer), good for you!  If you look at this code and think &#8220;yeah, that&#8217;s pretty cool chas, I dig that code!&#8221; then unhook the paint can from your face, keep reading, and promise me you won&#8217;t write any assert macros until you&#8217;re done.</p>
<p>OK we&#8217;ll go step by step here, in order of severity (and effect on sanity!).  Let&#8217;s start with the basics:</p>
<h2>1.  Always wrap your macro parameters in parentheses.</h2>
<p>Would you expect the following code to trigger an assert?</p>
<pre name="code" class="c++:nocontrols">
POW2_ASSERT(true || false);
</pre>
<p>The correct answer, by the way, is &#8220;absolutely not.&#8221;  But look at what it expands into when subjected to our awful assert macro:</p>
<pre name="code" class="c++:nocontrols">if (!true || false) { pow2::Assert::Fail(...); }</pre>
<p>Yeah, oops. &#8220;!true || false&#8221; of course collapses into &#8220;false&#8221;, which causes the assert to fire. Not what we want at all.  The standard fix is to always wrap your macro parameters in parentheses.  The corrected macro thus far now reads:</p>
<pre name="code" class="c++:nocontrols">#define POW2_ASSERT(x) \
    if (!(x)) { pow2::Assert::Fail(#x, __FILE__, __LINE__); }</pre>
<p>Not great, but slightly better.</p>
<h2>2.  Wrap your macros in do { &#8230; } while(0).</h2>
<p>What would you expect to have happen here?</p>
<pre name="code" class="c++:nocontrols">if (x == 3)
    POW2_ASSERT(y == 4);
else
    DoSomethingReallyImportant();</pre>
<p>The actual code is much different:</p>
<pre name="code" class="c++:nocontrols">if (x == 3)
    if (!(y == 4))
        pow2::Assert::Fail(...);
    else
        DoSomethingReallyImportant();</pre>
<p>Not so great. There are even scarier cases, too!  Anyway, the &#8216;canonical&#8217; and ugly-as-hell solution is to wrap your macros in a &#8220;do { &#8230; } while(0)&#8221; line.  Note the lack of semicolon at the end there, it&#8217;s very important.  It&#8217;s a surprisingly involved discussion that I won&#8217;t rehash because it&#8217;s in the comp.lang.c FAQ and you&#8217;re starting to get a little bored by now.  Don&#8217;t worry, the best fun is yet to come! </p>
<p>Here&#8217;s our best stab at assert yet:</p>
<pre name="code" class="c++:nocontrols">#define POW2_ASSERT(x) \
    do { if (!(x)) { pow2::Assert::Fail(#x, __FILE__, __LINE__); } } while(0)</pre>
<p> </p>
<h2>3.  Go away!  Sit in the corner, face the wall; I don&#8217;t want to even know you&#8217;re here.<br />
</h2>
<p>Asserts are great!  Let&#8217;s assert everywhere that our vectors are normalized!  Let&#8217;s assert that our strings are all exactly 12,592 bytes long by scanning for the first &#8216;\0&#8242;!  Let&#8217;s assert that every time we clear the back buffer, each pixel is set to burnt umber!  Let&#8217;s figure out why we&#8217;re only rendering at 1fps in release build!  Hmm.</p>
<p>A very nice thing to be able to do with assert is compile it out of existence.  The standard form looks something like this:</p>
<pre name="code" class="c++:nocontrols">#ifdef POW2_ASSERTS_ENABLED
    #define POW2_ASSERT(x) \
        do { if (!(x)) { pow2::Assert::Fail(#x, __FILE__, __LINE__); } } while(0)
#else
    #define POW2_ASSERT(x)
#endif</pre>
<p>OK, now it compiles out, and things are well and good, right? Sure, if you like spurious compiler warnings.</p>
<pre name="code" class="c++:nocontrols">const bool success = DoStuff();  POW2_ASSERT(success);</pre>
<p>Gives us this output (in MSVC8 but gcc gives an almost identical one):</p>
<pre>main.cpp(7) : warning C4189: 'success' : local variable is initialized but not referenced</pre>
<p>Not great.  These warnings only show up on MSVC&#8217;s (level 4) and gcc&#8217;s (-Wall) highest warning levels, but they can be valuable in other situations so we don&#8217;t want to disable them.  We can try the standard cast-to-void trick:</p>
<pre name="code" class="c++:nocontrols">#define POW2_ASSERT(x) do { (void)(x); } while(0)</pre>
<p>But then x is still evaluated.  Both gcc and MSVC are smart enough to optimize out the evaluation of x, but only if they can determine if  there are no side effects associated with the evaluation.  Unfortunately, this can only be done if the body of x is known entirely to the compiler.  If x is a function call to another module MSVC can still make it go away with Link-Time Code Generation (via cross-module inlining), but poor gcc is dead in the water and emits the call.  Either way, we&#8217;re relying on compiler and linker optimizations to make this code go away.</p>
<p>This code:</p>
<pre name="code" class="c++:nocontrols">int main(int, char*[])
{
    bool DoStuff(); // comes from another .cpp file
    POW2_ASSERT(DoStuff());
    return 0;
}</pre>
<p>Causes gcc (-O3 -pedantic -Wall &#8211;save-temps) to emit the following assembly:</p>
<pre>_main:
pushl %ebp
movl $16, %eax
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
call __alloca
call ___main
call __Z7DoStuffv
leave
xorl %eax, %eax
ret</pre>
<p>We&#8217;re not so crazy about the whole &#8220;call __Z7DoStuffv&#8221; line, but at least the compiler shut up.  We&#8217;re halfway there, I suppose.  The standard &#8220;UNUSED&#8221; macro has the same problem:</p>
<pre name="code" class="c++:nocontrols">#define POW2_UNUSED(x) do { (void)(x); } while(0)</pre>
<p>This can be useful for shutting up warnings during deep spelunking in the bowels of template code, but not here. The parameter is still evaluated and now we&#8217;ve also got this extra little clingy macro that follows our assert around everywhere. Nope, unused won&#8217;t do the trick here.</p>
<p>The best optimization you can ever do is to completely remove the code in question.  Both gcc and MSVC have pretty decent optimizing compilers, but why bother requiring them to be good at their jobs?  If there were a way we could force assert to boil down to nothing when we want and not emit any spurious warnings, we&#8217;d totally be money. </p>
<p>Boy, if only there were some C++ keyword that could syntactically accept almost anything and be guaranteed not to emit any code.</p>
<p>Enter the ever-humble sizeof keyword.  This little guy must be the absolute bane of C++ compiler writers.  Alexandrescu thoroughly exploits it in Modern C++ Design, and we can steal a page from his playbook here.  Let&#8217;s check the C++ Standard, (5.3.3), shall we?</p>
<p><em>The operand is either an expression, which is not evaluated, or a parenthesized type-id.<br />
</em><br />
Now I&#8217;m nowhere near as tricky as Alexandrescu or the slew of C++ luminaries who have discovered new and insane things to do with this awful language, but I know a useful keyword when I see it!  Baby, you had me at &#8220;which is not evaluated&#8221;.  Let&#8217;s rig it up and take it for a spin.  Note that gcc will correctly warn about the sizeof statement &#8220;having no effect,&#8221; but we can shut that up easily enough using the cast-to-void trick mentioned earlier:</p>
<pre name="code" class="c++:nocontrols">#define POW2_ASSERT(x) do { (void)sizeof(x); } while(0)</pre>
<p>Our old test case now emits the following assembly in gcc:</p>
<pre>_main:
pushl %ebp
movl $16, %eax
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
call __alloca
call ___main
leave
xorl %eax, %eax
ret</pre>
<p>And on MSVC8:</p>
<pre>_main PROC
xor eax, eax
ret 0
_main ENDP</pre>
<p>Our warnings are now silenced on both gcc and MSVC, too!  Looks pretty good to me. Let&#8217;s look at our final code, which is getting much closer to our quality bar:</p>
<pre name="code" class="c++:nocontrols">#ifdef POW2_ASSERTS_ENABLED
    #define POW2_ASSERT(x) \
        do { if (!(x)) { pow2::Assert::Fail(#x, __FILE__, __LINE__); } } while(0)
#else
    #define POW2_ASSERT(x) \
        do { (void)sizeof(x); } while(0)
#endif</pre>
<p> </p>
<h2>4.  Assert should always halt execution of the program, except for when it shouldn&#8217;t.</h2>
<p>The standard trick on Windows under MSVC to halt the program and break into the debugger is to use __debugbreak():</p>
<pre name="code" class="c++:nocontrols">#define POW2_HALT() __debugbreak()</pre>
<p>This is always what you want to do when your assert fires, right?  I mean, it&#8217;s an assert!  You can&#8217;t really continue gracefully, even if you wanted to.  Things are too insane.  That&#8217;s why you asserted in the first place!</p>
<p>Except maybe if you&#8217;re running unit tests.  If an assert fires inside a unit test, you probably don&#8217;t want a &#8220;friendly&#8221; modal dialog box to pop up and require you to hit abort, retry, or cancel.  You certainly don&#8217;t want that modal dialog box popping up on your poor automated build server.  You want to terminate that particular unit test and keep going.</p>
<p>That makes the requirements of your assert code a little more demanding.  Does it have to know if it&#8217;s running inside tests?  How can it possibly know these things even if you wanted to couple your code to your tests?  It can&#8217;t.  Not in any sort of clean way, anyway.  Not in any way that doesn&#8217;t couple your code too tightly for our comfort.</p>
<p>Assert::Fail hasn&#8217;t really been doing much of interest to date.  You&#8217;ve probably assumed that it prints the failed assert to the screen in a compiler-friendly format and then halt the program using a macro like POW2_HALT() above.  If it trampolined directly into a user-provided handler, it could report whether or not to terminate the program.  Let&#8217;s change it from:</p>
<pre name="code" class="c++:nocontrols">namespace pow2 { namespace Assert
{
    void Fail(char const* condition, char const* msg, char const* file, int line);
}}</pre>
<p>to this:</p>
<pre name="code" class="c++:nocontrols">
namespace pow2 { namespace Assert
{
	enum FailBehavior
	{
		Halt,
		Continue,
	};

	typedef FailBehavior (*Handler)(const char* condition,
                                    const char* msg,
                                    const char* file,
                                    int line);
	Handler GetHandler();
	void SetHandler(Handler newHandler);

	FailBehavior ReportFailure(const char* condition,
                               const char* file,
                               int line,
                               const char* msg, ...);
}}
</pre>
<p>We hide the current handler and default handler in Assert.cpp so as to keep our header file as simple as possible.  Now we can set any handler we want, and the app will only halt if the handler returns true. For our unit tests, our assert handler reports the assert to our testing framework, and the test fails gracefully.  Let&#8217;s beef up our macro yet again:</p>
<pre name="code" class="c++:nocontrols">
#ifdef POW2_ASSERTS_ENABLED
    #define POW2_ASSERT(cond) \
        do \
        { \
            if (!(cond)) \
            { \
                if (pow2::Assert::ReportFailure(#cond, __FILE__, __LINE__, 0) == \
                    pow2::Assert::Halt) \
                    POW2_HALT(); \
            } \
        } while(0)
#else
    #define POW2_ASSERT(condition) \
        do { POW2_UNUSED(condition); } while(0)
#endif
</pre>
<p>We&#8217;re in the home stretch!  This is actually our final code, but we&#8217;re not done discussing things yet.  Note also in the real <a href="http://cnicholson.net/wp-content/uploads/2009/02/pow2assert.h">Pow2Assert.h</a> there are overloaded forms of these macros that support variadic parameters for printf-style formatting.  I&#8217;ve omitted them here for brevity.<br />
 </p>
<h2>5.  Hooray!  My assert fired!  Where the hell am I?!</h2>
<p>The final common problem with assert macros is that they often leave you alone and lost in the wilderness, about 3 stack frames away from the code that actually triggered the assert.  I hope to inflict a violent emotional reaction by showing you this next image:</p>
<p><img class="size-full wp-image-7 alignnone" title="insano-callstack" src="http://cnicholson.net/wp-content/uploads/2009/02/insano-callstack.png" alt="Useless callstack from inside VS80 CRT &quot;assert&quot; function" width="668" height="179" /></p>
<p>Ahh yes.  Thanks a ton MSVC for taking me to&#8230;  _NMSG_WRITE(int rterrnum=10).  It&#8217;s at line 198 of crt0msg.c, if that helps you.  But it doesn&#8217;t.  Know why? Because it&#8217;s completely useless!  _NMSG_WRITE doesn&#8217;t have a damn thing to do with why our program is now dead.</p>
<p>The nicest side effect of item 4 (moving the POW2_HALT() back to the assert macro itself) is that the fired assert lands you in the debugger AT THE SITE OF THE FAILING ASSERT.  Sorry to yell, but it&#8217;s important.  Look at this call stack and tell me it&#8217;s not nicer:</p>
<p><img class="alignnone size-full wp-image-8" title="wonderful-callstack" src="http://cnicholson.net/wp-content/uploads/2009/02/wonderful-callstack.png" alt="wonderful-callstack" width="455" height="220" /></p>
<p>And we got it as a free side effect of making our assert macro cooler!</p>
<p>So that&#8217;s pretty much it for Assert.  I&#8217;m still tinkering with it every now and then, but it&#8217;s about as solid as I know how to make it at this point.  It&#8217;s certainly serving me well in the meantime. </p>
<p>Credit goes to Steve Rabin for his chapter in Game Programming Gems 1, it was the inspiration for item 5.  Thanks as always to Andrei Alexandrescu for opening my eyes to the sheer blinding madness of sizeof.  Tom Plunket was good enough to beat the do/while(0) stuff into me.</p>
]]></content:encoded>
			<wfw:commentRss>http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
	</channel>
</rss>

